Ada Bindings for wolfSSL. Credit Joakim Dahlgren Strandberg <joakimds@kth.se>

This commit is contained in:
David Garske 2023-07-12 10:46:09 -07:00
parent b8119af455
commit d20a096ffa
19 changed files with 2438 additions and 3 deletions

View File

@ -125,7 +125,7 @@ extern "C" {
#define WOLFSSL_DER_TO_PEM
#define WOLFSSL_CUSTOM_OID
#define HAVE_OID_ENCODING
//#define WOLFSSL_ASN_TEMPLATE /* Not enabled yet by default */
#define WOLFSSL_ASN_TEMPLATE
/* Certificate Revocation */
#define HAVE_OCSP

View File

@ -30648,9 +30648,9 @@ int wc_SetCustomExtension(Cert *cert, int critical, const char *oid,
ext = &cert->customCertExt[cert->customCertExtCount];
ext->oid = oid;
ext->oid = (char*)oid;
ext->crit = (critical == 0) ? 0 : 1;
ext->val = der;
ext->val = (byte*)der;
ext->valSz = derSz;
cert->customCertExtCount++;

22
wrapper/Ada/README.md Normal file
View File

@ -0,0 +1,22 @@
# Ada Binding Example
Download and install the GNAT community edition compiler and studio:
https://www.adacore.com/download
Linux Install:
```sh
chmod +x gnat-2021-20210519-x86_64-linux-bin
./gnat-2021-20210519-x86_64-linux-bin
```
```sh
export PATH="/opt/GNAT/2021/bin:$PATH"
gprclean
gprbuild default.gpr
./c_tls_server_main
./tls_server_main &
./c_tls_client_main 127.0.0.1
```

86
wrapper/Ada/ada_binding.c Normal file
View File

@ -0,0 +1,86 @@
/* ada_binding.c
*
* Copyright (C) 2006-2023 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
/* wolfSSL */
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/ssl.h>
// These functions give access to the integer values of the enumeration
// constants used in WolfSSL. These functions make it possible
// for the WolfSSL implementation to change the values of the constants
// without the need to make a corresponding change in the Ada code.
extern int get_wolfssl_success(void);
extern int get_wolfssl_verify_none(void);
extern int get_wolfssl_verify_peer(void);
extern int get_wolfssl_verify_fail_if_no_peer_cert(void);
extern int get_wolfssl_verify_client_once(void);
extern int get_wolfssl_verify_post_handshake(void);
extern int get_wolfssl_verify_fail_except_psk(void);
extern int get_wolfssl_verify_default(void);
extern int get_wolfssl_filetype_asn1(void);
extern int get_wolfssl_filetype_pem(void);
extern int get_wolfssl_filetype_default(void);
extern int get_wolfssl_success(void) {
return WOLFSSL_SUCCESS;
}
extern int get_wolfssl_verify_none(void) {
return WOLFSSL_VERIFY_NONE;
}
extern int get_wolfssl_verify_peer(void) {
return WOLFSSL_VERIFY_PEER;
}
extern int get_wolfssl_verify_fail_if_no_peer_cert(void) {
return WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT;
}
extern int get_wolfssl_verify_client_once(void) {
return WOLFSSL_VERIFY_CLIENT_ONCE;
}
extern int get_wolfssl_verify_post_handshake(void) {
return WOLFSSL_VERIFY_POST_HANDSHAKE;
}
extern int get_wolfssl_verify_fail_except_psk(void) {
return WOLFSSL_VERIFY_FAIL_EXCEPT_PSK;
}
extern int get_wolfssl_verify_default(void) {
return WOLFSSL_VERIFY_DEFAULT;
}
extern int get_wolfssl_filetype_asn1(void) {
return WOLFSSL_FILETYPE_ASN1;
}
extern int get_wolfssl_filetype_pem(void) {
return WOLFSSL_FILETYPE_PEM;
}
extern int get_wolfssl_filetype_default(void) {
return WOLFSSL_FILETYPE_DEFAULT;
}

View File

@ -0,0 +1,285 @@
/* c_tls_client_main.c
*
* Copyright (C) 2006-2023 wolfSSL Inc.
*
* This file is part of wolfSSL. (formerly known as CyaSSL)
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <wolfssl/wolfcrypt/settings.h>
/* the usual suspects */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/* socket includes */
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
/* wolfSSL */
#ifndef WOLFSSL_USER_SETTINGS
#include <wolfssl/options.h>
#endif
#include <wolfssl/ssl.h>
#include <wolfssl/wolfio.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#define DEFAULT_PORT 11111
#define CERT_FILE "../certs/client-cert.pem"
#define KEY_FILE "../certs/client-key.pem"
#define CA_FILE "../certs/ca-cert.pem"
#if defined(WOLFSSL_TLS13) && defined(HAVE_SECRET_CALLBACK)
#ifndef WOLFSSL_SSLKEYLOGFILE_OUTPUT
#define WOLFSSL_SSLKEYLOGFILE_OUTPUT "sslkeylog.log"
#endif
/* Callback function for TLS v1.3 secrets for use with Wireshark */
static int Tls13SecretCallback(WOLFSSL* ssl, int id, const unsigned char* secret,
int secretSz, void* ctx)
{
int i;
const char* str = NULL;
unsigned char clientRandom[32];
int clientRandomSz;
XFILE fp = stderr;
if (ctx) {
fp = XFOPEN((const char*)ctx, "ab");
if (fp == XBADFILE) {
return BAD_FUNC_ARG;
}
}
clientRandomSz = (int)wolfSSL_get_client_random(ssl, clientRandom,
sizeof(clientRandom));
if (clientRandomSz <= 0) {
printf("Error getting client random %d\n", clientRandomSz);
}
#if 0
printf("TLS Client Secret CB: Rand %d, Secret %d\n",
clientRandomSz, secretSz);
#endif
switch (id) {
case CLIENT_EARLY_TRAFFIC_SECRET:
str = "CLIENT_EARLY_TRAFFIC_SECRET"; break;
case EARLY_EXPORTER_SECRET:
str = "EARLY_EXPORTER_SECRET"; break;
case CLIENT_HANDSHAKE_TRAFFIC_SECRET:
str = "CLIENT_HANDSHAKE_TRAFFIC_SECRET"; break;
case SERVER_HANDSHAKE_TRAFFIC_SECRET:
str = "SERVER_HANDSHAKE_TRAFFIC_SECRET"; break;
case CLIENT_TRAFFIC_SECRET:
str = "CLIENT_TRAFFIC_SECRET_0"; break;
case SERVER_TRAFFIC_SECRET:
str = "SERVER_TRAFFIC_SECRET_0"; break;
case EXPORTER_SECRET:
str = "EXPORTER_SECRET"; break;
}
fprintf(fp, "%s ", str);
for (i = 0; i < clientRandomSz; i++) {
fprintf(fp, "%02x", clientRandom[i]);
}
fprintf(fp, " ");
for (i = 0; i < secretSz; i++) {
fprintf(fp, "%02x", secret[i]);
}
fprintf(fp, "\n");
if (fp != stderr) {
XFCLOSE(fp);
}
return 0;
}
#endif /* WOLFSSL_TLS13 && HAVE_SECRET_CALLBACK */
int main(int argc, char** argv)
{
int ret = 0;
#ifdef WOLFSSL_TLS13
int sockfd = SOCKET_INVALID;
struct sockaddr_in servAddr;
char buff[256];
size_t len;
/* declare wolfSSL objects */
WOLFSSL_CTX* ctx = NULL;
WOLFSSL* ssl = NULL;
/* Check for proper calling convention */
if (argc != 2) {
printf("usage: %s <IPv4 address>\n", argv[0]);
return 0;
}
/* Create a socket that uses an internet IPv4 address,
* Sets the socket to be stream based (TCP),
* 0 means choose the default protocol. */
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
fprintf(stderr, "ERROR: failed to create the socket\n");
ret = -1; goto exit;
}
/* Initialize the server address struct with zeros */
memset(&servAddr, 0, sizeof(servAddr));
/* Fill in the server address */
servAddr.sin_family = AF_INET; /* using IPv4 */
servAddr.sin_port = htons(DEFAULT_PORT); /* on DEFAULT_PORT */
/* Get the server IPv4 address from the command line call */
if (inet_pton(AF_INET, argv[1], &servAddr.sin_addr) != 1) {
fprintf(stderr, "ERROR: invalid address\n");
ret = -1; goto exit;
}
/* Connect to the server */
if ((ret = connect(sockfd, (struct sockaddr*) &servAddr, sizeof(servAddr)))
== -1) {
fprintf(stderr, "ERROR: failed to connect\n");
goto exit;
}
/*---------------------------------*/
/* Start of wolfSSL initialization and configuration */
/*---------------------------------*/
#if 0
wolfSSL_Debugging_ON();
#endif
/* Initialize wolfSSL */
if ((ret = wolfSSL_Init()) != WOLFSSL_SUCCESS) {
fprintf(stderr, "ERROR: Failed to initialize the library\n");
goto exit;
}
/* Create and initialize WOLFSSL_CTX */
if ((ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method())) == NULL) {
fprintf(stderr, "ERROR: failed to create WOLFSSL_CTX\n");
ret = -1; goto exit;
}
/* Load client certificate into WOLFSSL_CTX */
if ((ret = wolfSSL_CTX_use_certificate_file(ctx, CERT_FILE, WOLFSSL_FILETYPE_PEM))
!= WOLFSSL_SUCCESS) {
fprintf(stderr, "ERROR: failed to load %s, please check the file.\n",
CERT_FILE);
goto exit;
}
/* Load client key into WOLFSSL_CTX */
if ((ret = wolfSSL_CTX_use_PrivateKey_file(ctx, KEY_FILE, WOLFSSL_FILETYPE_PEM))
!= WOLFSSL_SUCCESS) {
fprintf(stderr, "ERROR: failed to load %s, please check the file.\n",
KEY_FILE);
goto exit;
}
/* Load CA certificate into WOLFSSL_CTX */
if ((ret = wolfSSL_CTX_load_verify_locations(ctx, CA_FILE, NULL))
!= WOLFSSL_SUCCESS) {
fprintf(stderr, "ERROR: failed to load %s, please check the file.\n",
CA_FILE);
goto exit;
}
/* Create a WOLFSSL object */
if ((ssl = wolfSSL_new(ctx)) == NULL) {
fprintf(stderr, "ERROR: failed to create WOLFSSL object\n");
ret = -1; goto exit;
}
/* Attach wolfSSL to the socket */
if ((ret = wolfSSL_set_fd(ssl, sockfd)) != WOLFSSL_SUCCESS) {
fprintf(stderr, "ERROR: Failed to set the file descriptor\n");
goto exit;
}
#ifdef HAVE_SECRET_CALLBACK
/* required for getting random used */
wolfSSL_KeepArrays(ssl);
/* optional logging for wireshark */
wolfSSL_set_tls13_secret_cb(ssl, Tls13SecretCallback,
(void*)WOLFSSL_SSLKEYLOGFILE_OUTPUT);
#endif
/* Connect to wolfSSL on the server side */
if ((ret = wolfSSL_connect(ssl)) != WOLFSSL_SUCCESS) {
fprintf(stderr, "ERROR: failed to connect to wolfSSL\n");
goto exit;
}
#ifdef HAVE_SECRET_CALLBACK
wolfSSL_FreeArrays(ssl);
#endif
/* Get a message for the server from stdin */
printf("Message for server: ");
memset(buff, 0, sizeof(buff));
if (fgets(buff, sizeof(buff), stdin) == NULL) {
fprintf(stderr, "ERROR: failed to get message for server\n");
ret = -1; goto exit;
}
len = strnlen(buff, sizeof(buff));
/* Send the message to the server */
if ((ret = wolfSSL_write(ssl, buff, len)) != (int)len) {
fprintf(stderr, "ERROR: failed to write entire message\n");
fprintf(stderr, "%d bytes of %d bytes were sent", ret, (int) len);
goto exit;
}
/* Read the server data into our buff array */
memset(buff, 0, sizeof(buff));
if ((ret = wolfSSL_read(ssl, buff, sizeof(buff)-1)) < 0) {
fprintf(stderr, "ERROR: failed to read\n");
goto exit;
}
/* Print to stdout any data the server sends */
printf("Server: %s\n", buff);
/* Return reporting a success */
ret = 0;
exit:
/* Cleanup and return */
if (sockfd != SOCKET_INVALID)
close(sockfd); /* Close the connection to the server */
if (ssl)
wolfSSL_free(ssl); /* Free the wolfSSL object */
if (ctx)
wolfSSL_CTX_free(ctx); /* Free the wolfSSL context object */
wolfSSL_Cleanup(); /* Cleanup the wolfSSL environment */
#else
printf("Example requires TLS v1.3\n");
#endif
(void)argc;
(void)argv;
return ret;
}

View File

@ -0,0 +1,361 @@
/* c_tls_server_main.c
*
* Copyright (C) 2006-2023 wolfSSL Inc.
*
* This file is part of wolfSSL. (formerly known as CyaSSL)
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <wolfssl/wolfcrypt/settings.h>
/* the usual suspects */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/* socket includes */
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#define HAVE_SIGNAL
#ifdef HAVE_SIGNAL
#include <signal.h> /* signal */
#endif
/* wolfSSL */
#ifndef WOLFSSL_USER_SETTINGS
#include <wolfssl/options.h>
#endif
#include <wolfssl/ssl.h>
#include <wolfssl/wolfio.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#define DEFAULT_PORT 11111
#define CERT_FILE "../certs/server-cert.pem"
#define KEY_FILE "../certs/server-key.pem"
#define CA_FILE "../certs/client-cert.pem"
#if defined(WOLFSSL_TLS13) && defined(HAVE_SECRET_CALLBACK)
#ifndef WOLFSSL_SSLKEYLOGFILE_OUTPUT
#define WOLFSSL_SSLKEYLOGFILE_OUTPUT "sslkeylog.log"
#endif
/* Callback function for TLS v1.3 secrets for use with Wireshark */
static int Tls13SecretCallback(WOLFSSL* ssl, int id, const unsigned char* secret,
int secretSz, void* ctx)
{
int i;
const char* str = NULL;
unsigned char serverRandom[32];
int serverRandomSz;
XFILE fp = stderr;
if (ctx) {
fp = XFOPEN((const char*)ctx, "ab");
if (fp == XBADFILE) {
return BAD_FUNC_ARG;
}
}
serverRandomSz = (int)wolfSSL_get_server_random(ssl, serverRandom,
sizeof(serverRandom));
if (serverRandomSz <= 0) {
printf("Error getting server random %d\n", serverRandomSz);
}
#if 0
printf("TLS Server Secret CB: Rand %d, Secret %d\n",
serverRandomSz, secretSz);
#endif
switch (id) {
case CLIENT_EARLY_TRAFFIC_SECRET:
str = "CLIENT_EARLY_TRAFFIC_SECRET"; break;
case EARLY_EXPORTER_SECRET:
str = "EARLY_EXPORTER_SECRET"; break;
case CLIENT_HANDSHAKE_TRAFFIC_SECRET:
str = "CLIENT_HANDSHAKE_TRAFFIC_SECRET"; break;
case SERVER_HANDSHAKE_TRAFFIC_SECRET:
str = "SERVER_HANDSHAKE_TRAFFIC_SECRET"; break;
case CLIENT_TRAFFIC_SECRET:
str = "CLIENT_TRAFFIC_SECRET_0"; break;
case SERVER_TRAFFIC_SECRET:
str = "SERVER_TRAFFIC_SECRET_0"; break;
case EXPORTER_SECRET:
str = "EXPORTER_SECRET"; break;
}
fprintf(fp, "%s ", str);
for (i = 0; i < (int)serverRandomSz; i++) {
fprintf(fp, "%02x", serverRandom[i]);
}
fprintf(fp, " ");
for (i = 0; i < secretSz; i++) {
fprintf(fp, "%02x", secret[i]);
}
fprintf(fp, "\n");
if (fp != stderr) {
XFCLOSE(fp);
}
return 0;
}
#endif /* WOLFSSL_TLS13 && HAVE_SECRET_CALLBACK */
static int mSockfd = SOCKET_INVALID;
static int mConnd = SOCKET_INVALID;
static int mShutdown = 0;
#ifdef HAVE_SIGNAL
static void sig_handler(const int sig)
{
fprintf(stderr, "SIGINT handled = %d.\n", sig);
mShutdown = 1;
if (mConnd != SOCKET_INVALID) {
close(mConnd); /* Close the connection to the client */
mConnd = SOCKET_INVALID;
}
if (mSockfd != SOCKET_INVALID) {
close(mSockfd); /* Close the socket listening for clients */
mSockfd = SOCKET_INVALID;
}
}
#endif
// To execute the application: ./main
int main(int argc, char** argv)
{
int ret = 0;
#ifdef WOLFSSL_TLS13
struct sockaddr_in servAddr;
struct sockaddr_in clientAddr;
socklen_t size = sizeof(clientAddr);
char buff[256];
size_t len;
const char* reply = "I hear ya fa shizzle!\n";
int on;
/* declare wolfSSL objects */
WOLFSSL_CTX* ctx = NULL;
WOLFSSL* ssl = NULL;
#ifdef HAVE_SIGNAL
signal(SIGINT, sig_handler);
#endif
/* Initialize the server address struct with zeros */
memset(&servAddr, 0, sizeof(servAddr));
/* Fill in the server address */
servAddr.sin_family = AF_INET; /* using IPv4 */
servAddr.sin_port = htons(DEFAULT_PORT); /* on DEFAULT_PORT */
servAddr.sin_addr.s_addr = INADDR_ANY; /* from anywhere */
/* Create a socket that uses an internet IPv4 address,
* Sets the socket to be stream based (TCP),
* 0 means choose the default protocol. */
if ((mSockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
fprintf(stderr, "ERROR: failed to create the socket\n");
goto exit;
}
/* make sure server is setup for reuse addr/port */
on = 1;
setsockopt(mSockfd, SOL_SOCKET, SO_REUSEADDR,
(char*)&on, (socklen_t)sizeof(on));
#ifdef SO_REUSEPORT
setsockopt(mSockfd, SOL_SOCKET, SO_REUSEPORT,
(char*)&on, (socklen_t)sizeof(on));
#endif
/* Bind the server socket to our port */
if (bind(mSockfd, (struct sockaddr*)&servAddr, sizeof(servAddr)) == -1) {
fprintf(stderr, "ERROR: failed to bind\n");
goto exit;
}
/* Listen for a new connection, allow 5 pending connections */
if (listen(mSockfd, 5) == -1) {
fprintf(stderr, "ERROR: failed to listen\n");
goto exit;
}
/*---------------------------------*/
/* Start of wolfSSL initialization and configuration */
/*---------------------------------*/
#if 0
wolfSSL_Debugging_ON();
#endif
/* Initialize wolfSSL */
if ((ret = wolfSSL_Init()) != WOLFSSL_SUCCESS) {
fprintf(stderr, "ERROR: Failed to initialize the library\n");
goto exit;
}
/* Create and initialize WOLFSSL_CTX */
if ((ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method())) == NULL) {
fprintf(stderr, "ERROR: failed to create WOLFSSL_CTX\n");
ret = -1;
goto exit;
}
/* Require mutual authentication */
wolfSSL_CTX_set_verify(ctx,
WOLFSSL_VERIFY_PEER | WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
/* Load server certificates into WOLFSSL_CTX */
if ((ret = wolfSSL_CTX_use_certificate_file(ctx, CERT_FILE,
WOLFSSL_FILETYPE_PEM)) != WOLFSSL_SUCCESS) {
fprintf(stderr, "ERROR: failed to load %s, please check the file.\n",
CERT_FILE);
goto exit;
}
/* Load server key into WOLFSSL_CTX */
if ((ret = wolfSSL_CTX_use_PrivateKey_file(ctx, KEY_FILE,
WOLFSSL_FILETYPE_PEM)) != WOLFSSL_SUCCESS) {
fprintf(stderr, "ERROR: failed to load %s, please check the file.\n",
KEY_FILE);
goto exit;
}
/* Load client certificate as "trusted" into WOLFSSL_CTX */
if ((ret = wolfSSL_CTX_load_verify_locations(ctx, CA_FILE, NULL))
!= WOLFSSL_SUCCESS) {
fprintf(stderr, "ERROR: failed to load %s, please check the file.\n",
CA_FILE);
goto exit;
}
/* Continue to accept clients until mShutdown is issued */
while (!mShutdown) {
printf("Waiting for a connection...\n");
/* Accept client connections */
if ((mConnd = accept(mSockfd, (struct sockaddr*)&clientAddr, &size))
== -1) {
fprintf(stderr, "ERROR: failed to accept the connection\n\n");
ret = -1; goto exit;
}
/* Create a WOLFSSL object */
if ((ssl = wolfSSL_new(ctx)) == NULL) {
fprintf(stderr, "ERROR: failed to create WOLFSSL object\n");
ret = -1; goto exit;
}
/* Attach wolfSSL to the socket */
wolfSSL_set_fd(ssl, mConnd);
#ifdef HAVE_SECRET_CALLBACK
/* required for getting random used */
wolfSSL_KeepArrays(ssl);
/* optional logging for wireshark */
wolfSSL_set_tls13_secret_cb(ssl, Tls13SecretCallback,
(void*)WOLFSSL_SSLKEYLOGFILE_OUTPUT);
#endif
/* Establish TLS connection */
if ((ret = wolfSSL_accept(ssl)) != WOLFSSL_SUCCESS) {
fprintf(stderr, "wolfSSL_accept error = %d\n",
wolfSSL_get_error(ssl, ret));
goto exit;
}
printf("Client connected successfully\n");
#ifdef HAVE_SECRET_CALLBACK
wolfSSL_FreeArrays(ssl);
#endif
/* Read the client data into our buff array */
memset(buff, 0, sizeof(buff));
if ((ret = wolfSSL_read(ssl, buff, sizeof(buff)-1)) < 0) {
fprintf(stderr, "ERROR: failed to read\n");
goto exit;
}
/* Print to stdout any data the client sends */
printf("Client: %s\n", buff);
/* Check for server shutdown command */
if (strncmp(buff, "shutdown", 8) == 0) {
printf("Shutdown command issued!\n");
mShutdown = 1;
}
/* Write our reply into buff */
memset(buff, 0, sizeof(buff));
memcpy(buff, reply, strlen(reply));
len = strnlen(buff, sizeof(buff));
/* Reply back to the client */
if ((ret = wolfSSL_write(ssl, buff, len)) != (int)len) {
fprintf(stderr, "ERROR: failed to write\n");
goto exit;
}
/* Cleanup after this connection */
wolfSSL_shutdown(ssl);
if (ssl) {
wolfSSL_free(ssl); /* Free the wolfSSL object */
ssl = NULL;
}
if (mConnd != SOCKET_INVALID) {
close(mConnd); /* Close the connection to the client */
mConnd = SOCKET_INVALID;
}
}
printf("Shutdown complete\n");
exit:
/* Cleanup and return */
if (ssl)
wolfSSL_free(ssl); /* Free the wolfSSL object */
if (mConnd != SOCKET_INVALID) {
close(mConnd); /* Close the connection to the client */
mConnd = SOCKET_INVALID;
}
if (mSockfd != SOCKET_INVALID) {
close(mSockfd); /* Close the socket listening for clients */
mSockfd = SOCKET_INVALID;
}
if (ctx)
wolfSSL_CTX_free(ctx); /* Free the wolfSSL context object */
wolfSSL_Cleanup(); /* Cleanup the wolfSSL environment */
#else
printf("Example requires TLS v1.3\n");
#endif /* WOLFSSL_TLS13 */
(void)argc;
(void)argv;
return ret;
}

69
wrapper/Ada/default.gpr Normal file
View File

@ -0,0 +1,69 @@
project Default is
for Languages use ("C", "Ada");
for Source_Dirs use (".",
"../../",
"../../src",
"../../wolfcrypt/src");
for Object_Dir use "obj";
for Main use ("c_tls_client_main.c",
"c_tls_server_main.c",
"tls_server_main.adb");
package Naming is
for Spec_Suffix ("C") use ".h";
end Naming;
package Builder is
for Global_Configuration_Pragmas use "gnat.adc";
end Builder;
package Compiler is
for Switches ("C") use
("-DWOLFSSL_USER_SETTINGS",
"-Wno-pragmas",
"-Wall",
"-Wextra",
"-Wunknown-pragmas",
"--param=ssp-buffer-size=1",
"-Waddress",
"-Warray-bounds",
"-Wbad-function-cast",
"-Wchar-subscripts",
"-Wcomment",
"-Wfloat-equal",
"-Wformat-security",
"-Wformat=2",
"-Wmaybe-uninitialized",
"-Wmissing-field-initializers",
"-Wmissing-noreturn",
"-Wmissing-prototypes",
"-Wnested-externs",
"-Wnormalized=id",
"-Woverride-init",
"-Wpointer-arith",
"-Wpointer-sign",
"-Wshadow",
"-Wsign-compare",
"-Wstrict-overflow=1",
"-Wstrict-prototypes",
"-Wswitch-enum",
"-Wundef",
"-Wunused",
"-Wunused-result",
"-Wunused-variable",
"-Wwrite-strings",
"-fwrapv");
end Compiler;
package Linker is
for Switches ("C") use
("-lm"); -- To include the math library (used by WolfSSL).
for Switches ("Ada") use
("-lm"); -- To include the math library (used by WolfSSL).
end Linker;
end Default;

1
wrapper/Ada/gnat.adc Normal file
View File

@ -0,0 +1 @@
pragma Restrictions (No_Secondary_Stack);

19
wrapper/Ada/include.am Normal file
View File

@ -0,0 +1,19 @@
# vim:ft=automake
# included from Top Level Makefile.am
# All paths should be given relative to the root
EXTRA_DIST+= wrapper/Ada/README.md
EXTRA_DIST+= wrapper/Ada/default.gpr
EXTRA_DIST+= wrapper/Ada/gnat.adc
EXTRA_DIST+= wrapper/Ada/ada_binding.c
EXTRA_DIST+= wrapper/Ada/c_tls_client_main.c
EXTRA_DIST+= wrapper/Ada/c_tls_server_main.c
EXTRA_DIST+= wrapper/Ada/tls_client_main.adb
EXTRA_DIST+= wrapper/Ada/tls_client.adb
EXTRA_DIST+= wrapper/Ada/tls_client.ads
EXTRA_DIST+= wrapper/Ada/tls_server_main.adb
EXTRA_DIST+= wrapper/Ada/tls_server.adb
EXTRA_DIST+= wrapper/Ada/tls_server.ads
EXTRA_DIST+= wrapper/Ada/user_settings.h
EXTRA_DIST+= wrapper/Ada/wolfssl.adb
EXTRA_DIST+= wrapper/Ada/wolfssl.ads

View File

@ -0,0 +1,81 @@
-- Ada Standard Library packages.
with Ada.Characters.Handling;
with Ada.Command_Line;
with Ada.Strings.Bounded;
with Ada.Text_IO.Bounded_IO;
-- GNAT Library packages.
with GNAT.Sockets;
-- The WolfSSL package.
with WolfSSL;
package body Tls_Client is
use type WolfSSL.Mode_Type;
use type WolfSSL.Byte_Index;
use type WolfSSL.Byte_Array;
use all type WolfSSL.Subprogram_Result;
package Messages is new Ada.Strings.Bounded.Generic_Bounded_Length (Max => 200);
use all type Messages.Bounded_String;
package Messages_IO is new Ada.Text_IO.Bounded_IO (Messages);
procedure Put_Line (Text : String) is
begin
Ada.Text_IO.Put_Line (Text);
end Put_Line;
procedure Put_Line (Text : Messages.Bounded_String) is
begin
Messages_IO.Put_Line (Text);
end Put_Line;
subtype Exit_Status is Ada.Command_Line.Exit_Status;
Exit_Status_Success : Exit_Status renames Ada.Command_Line.Success;
Exit_Status_Failure : Exit_Status renames Ada.Command_Line.Failure;
procedure Set (Status : Exit_Status) is
begin
Ada.Command_Line.Set_Exit_Status (Status);
end Set;
subtype Port_Type is GNAT.Sockets.Port_Type;
subtype Level_Type is GNAT.Sockets.Level_Type;
subtype Socket_Type is GNAT.Sockets.Socket_Type;
subtype Option_Name is GNAT.Sockets.Option_Name;
subtype Option_Type is GNAT.Sockets.Option_Type;
subtype Family_Type is GNAT.Sockets.Family_Type;
subtype Sock_Addr_Type is GNAT.Sockets.Sock_Addr_Type;
subtype Inet_Addr_Type is GNAT.Sockets.Inet_Addr_Type;
Socket_Error : exception renames GNAT.Sockets.Socket_Error;
Reuse_Address : Option_Name renames GNAT.Sockets.Reuse_Address;
Socket_Level : Level_Type renames GNAT.Sockets.Socket_Level;
Family_Inet : Family_Type renames GNAT.Sockets.Family_Inet;
Any_Inet_Addr : Inet_Addr_Type renames GNAT.Sockets.Any_Inet_Addr;
CERT_FILE : constant String := "../certs/server-cert.pem";
KEY_FILE : constant String := "../certs/server-key.pem";
CA_FILE : constant String := "../certs/client-cert.pem";
subtype Byte_Array is WolfSSL.Byte_Array;
procedure Run is
A : Sock_Addr_Type;
C : Socket_Type; -- Client socket.
begin
null; -- work in progress.
end Run;
end Tls_Client;

View File

@ -0,0 +1,5 @@
package Tls_Client is
procedure Run;
end Tls_Client;

View File

@ -0,0 +1,8 @@
with Tls_Client; pragma Elaborate_All (Tls_Client);
-- Application entry point for the Ada translation of the
-- tls client v1.3 example in C.
procedure Tls_Client_Main is
begin
Tls_Client.Run;
end Tls_Client_Main;

240
wrapper/Ada/tls_server.adb Normal file
View File

@ -0,0 +1,240 @@
-- Ada Standard Library packages.
with Ada.Characters.Handling;
with Ada.Command_Line;
with Ada.Strings.Bounded;
with Ada.Text_IO.Bounded_IO;
-- GNAT Library packages.
with GNAT.Sockets;
-- The WolfSSL package.
with WolfSSL;
package body Tls_Server is
use type WolfSSL.Mode_Type;
use type WolfSSL.Byte_Index;
use type WolfSSL.Byte_Array;
use all type WolfSSL.Subprogram_Result;
package Messages is new Ada.Strings.Bounded.Generic_Bounded_Length (Max => 200);
use all type Messages.Bounded_String;
package Messages_IO is new Ada.Text_IO.Bounded_IO (Messages);
procedure Put_Line (Text : String) is
begin
Ada.Text_IO.Put_Line (Text);
end Put_Line;
procedure Put_Line (Text : Messages.Bounded_String) is
begin
Messages_IO.Put_Line (Text);
end Put_Line;
subtype Exit_Status is Ada.Command_Line.Exit_Status;
Exit_Status_Success : Exit_Status renames Ada.Command_Line.Success;
Exit_Status_Failure : Exit_Status renames Ada.Command_Line.Failure;
procedure Set (Status : Exit_Status) is
begin
Ada.Command_Line.Set_Exit_Status (Status);
end Set;
subtype Port_Type is GNAT.Sockets.Port_Type;
subtype Level_Type is GNAT.Sockets.Level_Type;
subtype Socket_Type is GNAT.Sockets.Socket_Type;
subtype Option_Name is GNAT.Sockets.Option_Name;
subtype Option_Type is GNAT.Sockets.Option_Type;
subtype Family_Type is GNAT.Sockets.Family_Type;
subtype Sock_Addr_Type is GNAT.Sockets.Sock_Addr_Type;
subtype Inet_Addr_Type is GNAT.Sockets.Inet_Addr_Type;
Socket_Error : exception renames GNAT.Sockets.Socket_Error;
Reuse_Address : Option_Name renames GNAT.Sockets.Reuse_Address;
Socket_Level : Level_Type renames GNAT.Sockets.Socket_Level;
Family_Inet : Family_Type renames GNAT.Sockets.Family_Inet;
Any_Inet_Addr : Inet_Addr_Type renames GNAT.Sockets.Any_Inet_Addr;
CERT_FILE : constant String := "../certs/server-cert.pem";
KEY_FILE : constant String := "../certs/server-key.pem";
CA_FILE : constant String := "../certs/client-cert.pem";
subtype Byte_Array is WolfSSL.Byte_Array;
Reply : constant Byte_Array := "I hear ya fa shizzle!";
procedure Run is
A : Sock_Addr_Type;
L : Socket_Type; -- Listener socket.
C : Socket_Type; -- Client socket.
P : constant Port_Type := 11111;
Ch : Character;
Ssl : WolfSSL.Optional_WolfSSL;
Ctx : WolfSSL.Optional_Context;
Result : WolfSSL.Subprogram_Result;
M : Messages.Bounded_String;
Shall_Continue : Boolean := True;
Bytes_Written : Integer;
Input : WolfSSL.Read_Result;
begin
GNAT.Sockets.Create_Socket (Socket => L);
GNAT.Sockets.Set_Socket_Option (Socket => L,
Level => Socket_Level,
Option => (Name => Reuse_Address,
Enabled => True));
GNAT.Sockets.Bind_Socket (Socket => L,
Address => (Family => Family_Inet,
Addr => Any_Inet_Addr,
Port => P));
GNAT.Sockets.Listen_Socket (Socket => L,
Length => 5);
-- Create and initialize WOLFSSL_CTX.
WolfSSL.Create_Context (Method => WolfSSL.TLSv1_3_Server_Method,
Context => Ctx);
if not Ctx.Exists then
Put_Line ("ERROR: failed to create WOLFSSL_CTX.");
Set (Exit_Status_Failure);
return;
end if;
-- Require mutual authentication.
WolfSSL.Set_Verify
(Context => Ctx.Instance,
Mode => WolfSSL.Verify_Peer & WolfSSL.Verify_Fail_If_No_Peer_Cert);
-- Load server certificates into WOLFSSL_CTX.
Result := WolfSSL.Use_Certificate_File (Context => Ctx.Instance,
File => CERT_FILE,
Format => WolfSSL.Format_Pem);
if Result = Failure then
M := Messages.To_Bounded_String ("ERROR: failed to load ");
Messages.Append (M, CERT_FILE);
Messages.Append (M, ", please check the file.");
Put_Line (M);
Set (Exit_Status_Failure);
return;
end if;
-- Load server key into WOLFSSL_CTX.
Result := WolfSSL.Use_Private_Key_File (Context => Ctx.Instance,
File => KEY_FILE,
Format => WolfSSL.Format_Pem);
if Result = Failure then
M := Messages.To_Bounded_String ("ERROR: failed to load ");
Messages.Append (M, KEY_FILE);
Messages.Append (M, ", please check the file.");
Put_Line (M);
Set (Exit_Status_Failure);
return;
end if;
Put_Line ("success to here at least");
-- Load client certificate as "trusted" into WOLFSSL_CTX.
Result := WolfSSL.Load_Verify_Locations (Context => Ctx.Instance,
File => CA_FILE,
Path => "");
if Result = Failure then
M := Messages.To_Bounded_String ("ERROR: failed to load ");
Messages.Append (M, CA_FILE);
Messages.Append (M, ", please check the file.");
Put_Line (M);
Set (Exit_Status_Failure);
return;
end if;
while Shall_Continue loop
Put_Line ("Waiting for a connection...");
begin
GNAT.Sockets.Accept_Socket (Server => L,
Socket => C,
Address => A);
exception
when Socket_Error =>
Shall_Continue := False;
Put_Line ("ERROR: failed to accept the connection.");
end;
-- Create a WOLFSSL object.
WolfSSL.Create_WolfSSL (Context => Ctx.Instance, Ssl => Ssl);
if not Ssl.Exists then
Put_Line ("ERROR: failed to create WOLFSSL object.");
Set (Exit_Status_Failure);
return;
end if;
-- Attach wolfSSL to the socket.
Result := WolfSSL.Attach (Ssl => Ssl.Instance,
Socket => GNAT.Sockets.To_C (C));
-- Establish TLS connection.
Result := WolfSSL.Accept_Connection (Ssl.Instance);
if Result = Failure then
Put_Line ("Accept error.");
Set (Exit_Status_Failure);
return;
end if;
Put_Line ("Client connected successfully.");
Input := WolfSSL.Read (Ssl.Instance);
if Input.Result /= Success then
Put_Line ("Read error.");
Set (Exit_Status_Failure);
return;
end if;
-- Print to stdout any data the client sends.
M := Messages.To_Bounded_String ("");
for I in Input.Buffer'Range loop
Ch := Character (Input.Buffer (I));
if Ada.Characters.Handling.Is_Graphic (Ch) then
Messages.Append (M, Ch);
else
null;
-- Ignore the "newline" characters at end of message.
end if;
end loop;
Put_Line (M);
-- Check for server shutdown command.
if Input.Last >= 8 then
if Input.Buffer (1 .. 8) = "shutdown" then
Put_Line ("Shutdown command issued!");
Shall_Continue := False;
end if;
end if;
Bytes_Written := WolfSSL.Write (Ssl.Instance, Reply);
if Bytes_Written /= Reply'Length then
Put_Line ("ERROR: failed to write.");
end if;
Result := WolfSSL.Shutdown (Ssl.Instance);
WolfSSL.Free (Ssl);
GNAT.Sockets.Close_Socket (C);
Put_Line ("Shutdown complete.");
end loop;
GNAT.Sockets.Close_Socket (L);
WolfSSL.Free (Context => Ctx);
WolfSSL.Finalize;
end Run;
end Tls_Server;

View File

@ -0,0 +1,5 @@
package Tls_Server is
procedure Run;
end Tls_Server;

View File

@ -0,0 +1,8 @@
with Tls_Server; pragma Elaborate_All (Tls_Server);
-- Application entry point for the Ada translation of the
-- tls server v1.3 example in C.
procedure Tls_Server_Main is
begin
Tls_Server.Run;
end Tls_Server_Main;

385
wrapper/Ada/user_settings.h Normal file
View File

@ -0,0 +1,385 @@
/* user_settings.h
*
* Copyright (C) 2006-2023 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
/* should be renamed to user_settings.h for customer use
* generated from configure options ./configure --enable-all
*
* Cleaned up by David Garske
*/
#ifndef WOLFSSL_USER_SETTINGS_H
#define WOLFSSL_USER_SETTINGS_H
#ifdef __cplusplus
extern "C" {
#endif
/* Usually comes from configure -> config.h */
#define HAVE_SYS_TIME_H
/* Features */
#define SINGLE_THREADED
#define WOLFSSL_IGNORE_FILE_WARN /* Ignore *.c include warnings */
#define WOLFSSL_PUBLIC_MP /* Make math API's public */
#define WOLFSSL_ENCRYPTED_KEYS /* Support for encrypted keys PKCS8 */
#define WOLFSSL_SYS_CA_CERTS /* Enable ability to load CA certs from OS */
#if 0 /* Not needed */
#define KEEP_PEER_CERT /* Retain peer's certificate */
#define KEEP_OUR_CERT /* Keep our certificate */
#define WOLFSSL_ALWAYS_VERIFY_CB /* Always call verify callback (configured via wolfSSL_CTX_set_verify API) */
#define WOLFSSL_VERIFY_CB_ALL_CERTS /* Call verify callback for all intermediate certs */
#define WOLFSSL_ALWAYS_KEEP_SNI
#define WOLFSSL_EXTRA_ALERTS /* Allow sending other TLS alerts */
#define HAVE_EX_DATA /* Enable "extra" EX data API's for user information in CTX/WOLFSSL */
#define HAVE_EXT_CACHE
#define ATOMIC_USER /* Enable Atomic Record Layer callbacks */
#define HAVE_PK_CALLBACKS /* Enable public key callbacks */
#define WOLFSSL_ALT_NAMES /* Allow alternate cert chain validation to any trusted cert (not entire chain presented by peer) */
#define HAVE_NULL_CIPHER /* Enable use of TLS cipher suites without cipher (clear text / no encryption) */
#define WOLFSSL_HAVE_CERT_SERVICE
#define WOLFSSL_JNI
#define WOLFSSL_SEP /* certificate policy set extension */
#define WOLFCRYPT_HAVE_SRP
#define WOLFSSL_HAVE_WOLFSCEP
#define HAVE_PKCS7
#define WOLFSSL_SIGNER_DER_CERT
#define WOLFSSL_TRUST_PEER_CERT
#define WOLFSSL_WOLFSSH
#define WC_NO_ASYNC_THREADING
#endif
/* TLS Features */
#define WOLFSSL_TLS13
#define WOLFSSL_EITHER_SIDE /* allow generic server/client method for WOLFSSL_CTX new */
#define WOLFSSL_TLS13_NO_PEEK_HANDSHAKE_DONE
/* DTLS */
#if 0
#define WOLFSSL_DTLS
#define WOLFSSL_MULTICAST
/* DTLS v1.3 is not yet included with enable-all */
//#define WOLFSSL_DTLS13
#endif
/* DG Disabled SSLv3 and TLSv1.0 - should avoid using */
//#define WOLFSSL_ALLOW_SSLV3
//#define WOLFSSL_ALLOW_TLSV10
/* TLS Extensions */
#define HAVE_TLS_EXTENSIONS
#define HAVE_SUPPORTED_CURVES
#define HAVE_ONE_TIME_AUTH
#define HAVE_SNI
#define HAVE_ALPN
#define HAVE_MAX_FRAGMENT
#define HAVE_TRUNCATED_HMAC
#define HAVE_SESSION_TICKET
#define WOLFSSL_TICKET_HAVE_ID
#define WOLFSSL_FORCE_CACHE_ON_TICKET
#define HAVE_EXTENDED_MASTER
#define HAVE_TRUSTED_CA
#define HAVE_ENCRYPT_THEN_MAC
#define WOLFSSL_POST_HANDSHAKE_AUTH
#define WOLFSSL_SEND_HRR_COOKIE /* Used by DTLS v1.3 */
#define HAVE_ANON /* anon cipher suites */
#define HAVE_FALLBACK_SCSV /* TLS_FALLBACK_SCSV */
#define WOLFSSL_EARLY_DATA
#define HAVE_SERVER_RENEGOTIATION_INFO
/* TLS Session Cache */
#define SESSION_CERTS
#define PERSIST_SESSION_CACHE
#define PERSIST_CERT_CACHE
/* Key and Certificate Generation */
#define WOLFSSL_KEY_GEN
#define WOLFSSL_CERT_GEN
#define WOLFSSL_CERT_REQ
#define WOLFSSL_CERT_EXT
#define WOLFSSL_MULTI_ATTRIB
#define HAVE_SMIME
#define WOLFSSL_DER_LOAD
#define ASN_BER_TO_DER /* BER to DER support */
#define WOLFSSL_HAVE_ISSUER_NAMES /* Store pointers to issuer name components and their lengths and encodings */
#define WOLFSSL_SUBJ_DIR_ATTR /* Enable support for SubjectDirectoryAttributes extension */
#define WOLFSSL_SUBJ_INFO_ACC /* Enable support for SubjectInfoAccess extension */
#define WOLFSSL_CERT_NAME_ALL /* Adds more certificate name capability at the cost of taking up more memory. Adds initials, givenname, dnQualifer for example */
#define WOLFSSL_FPKI /* Enable support for FPKI (Federal PKI) extensions */
#define WOLFSSL_AKID_NAME /* Enable support for full AuthorityKeyIdentifier extension. Only supports copying full AKID from an existing certificate */
#define HAVE_CTS /* Ciphertext stealing interface */
#define WOLFSSL_PEM_TO_DER
#define WOLFSSL_DER_TO_PEM
#define WOLFSSL_CUSTOM_OID
#define HAVE_OID_ENCODING
#define WOLFSSL_ASN_TEMPLATE
/* Certificate Revocation */
#define HAVE_OCSP
#define HAVE_CERTIFICATE_STATUS_REQUEST
#define HAVE_CERTIFICATE_STATUS_REQUEST_V2
#define HAVE_CRL
#define HAVE_CRL_IO
#define HAVE_IO_TIMEOUT
//#define HAVE_CRL_MONITOR /* DG Disabled (Monitors CRL files on filesystem) - not portable feature */
#if 1
/* sp_int.c */
#define WOLFSSL_SP_MATH_ALL
#else
/* Fast math key size 4096-bit max */
#define USE_FAST_MATH
#endif
//#define HAVE___UINT128_T 1 /* DG commented: May not be portable */
/* Max Sizes */
#define RSA_MAX_SIZE 4096
#define FP_MAX_BITS 8192
#define SP_INT_BITS 4096
/* Timing Resistance */
#define TFM_TIMING_RESISTANT
#define ECC_TIMING_RESISTANT
#define WC_RSA_BLINDING
/* DH Key Sizes */
#define HAVE_FFDHE_2048
#define HAVE_FFDHE_3072
#define WOLFSSL_DH_EXTRA /* Enable additional DH key import/export */
#define HAVE_DH_DEFAULT_PARAMS
/* ECC Features */
#define HAVE_ECC
#define TFM_ECC256
#define ECC_SHAMIR
#define WOLFSSL_CUSTOM_CURVES /* enable other curves (not just prime) */
#define HAVE_ECC_SECPR2
#define HAVE_ECC_SECPR3
#define HAVE_ECC_BRAINPOOL
#define HAVE_ECC_KOBLITZ
#define HAVE_ECC_CDH /* Co-factor */
#define HAVE_COMP_KEY /* Compressed key support */
#define FP_ECC /* Fixed point caching - speed repeated operations against same key */
#define HAVE_ECC_ENCRYPT
#define WOLFCRYPT_HAVE_ECCSI
#define WOLFCRYPT_HAVE_SAKKE
#define WOLFSSL_ECDSA_DETERMINISTIC_K_VARIANT
/* RSA */
#define WC_RSA_PSS
#define WOLFSSL_PSS_LONG_SALT
#define WC_RSA_NO_PADDING
/* AES */
#define HAVE_AES_DECRYPT
#define HAVE_AES_ECB
#define WOLFSSL_AES_DIRECT
#define WOLFSSL_AES_COUNTER
#define HAVE_AESGCM
#define GCM_TABLE_4BIT
#define WOLFSSL_AESGCM_STREAM
#define HAVE_AESCCM
#define WOLFSSL_AES_OFB
#define WOLFSSL_AES_CFB
#define WOLFSSL_AES_XTS
#define HAVE_AES_KEYWRAP
#define WOLFSSL_AES_CBC_LENGTH_CHECKS
#define WOLFSSL_USE_ALIGN
#define WOLFSSL_AES_SIV
/* Hashing */
#define WOLFSSL_SHA224
#define WOLFSSL_SHA512
#define WOLFSSL_SHA384
#define WOLFSSL_SHAKE256
#define WOLFSSL_SHA3
#define WOLFSSL_HASH_FLAGS /* enable hash flag API's */
#define WOLFSSL_SHAKE256
/* Additional Algorithms */
#define HAVE_HASHDRBG
#define HAVE_CURVE25519
#define HAVE_ED25519
#define WOLFSSL_ED25519_STREAMING_VERIFY
#define CURVED25519_SMALL
#define HAVE_ED448
#define WOLFSSL_ED448_STREAMING_VERIFY
#define HAVE_CURVE448
#define HAVE_POLY1305
#define HAVE_CHACHA
#define HAVE_XCHACHA
#define HAVE_HKDF
#define HAVE_X963_KDF
#define WOLFSSL_CMAC
#define WOLFSSL_DES_ECB
#define HAVE_BLAKE2
#define HAVE_BLAKE2B
#define HAVE_BLAKE2S
#define WOLFSSL_SIPHASH
#define HAVE_KEYING_MATERIAL
#define WOLFSSL_HAVE_PRF
/* Encrypted Client Hello */
#define HAVE_HPKE
#define HAVE_ECH
/* Non-Standard Algorithms (DG disabled) */
//#define HAVE_CAMELLIA
//#define WOLFSSL_RIPEMD
//#define HAVE_SCRYPT
//#define WOLFSSL_MD2
//#define WOLFSSL_ALLOW_RC4
/* Encoding */
#define WOLFSSL_BASE16
#define WOLFSSL_BASE64_ENCODE
/* Openssl compatibility */
#if 0 /* DG Disabled */
/* Openssl compatibility API's */
#define OPENSSL_EXTRA
#define OPENSSL_ALL
#define HAVE_OPENSSL_CMD
#define SSL_TXT_TLSV1_2
#define SSL_TXT_TLSV1_1
#define OPENSSL_NO_SSL2
#define OPENSSL_NO_SSL3
#define NO_OLD_RNGNAME
#define NO_OLD_WC_NAMES
#define NO_OLD_SSL_NAMES
#define NO_OLD_SHA_NAMES
#define NO_OLD_MD5_NAME
#define OPENSSL_NO_EC /* macro to enable ECC in openssl */
#define WOLFSSL_VERBOSE_ERRORS
#define ERROR_QUEUE_PER_THREAD
#define WOLFSSL_ERROR_CODE_OPENSSL
#define HAVE_WOLFSSL_SSL_H 1
#define OPENSSL_COMPATIBLE_DEFAULTS
/* Openssl compatibility application specific */
#define WOLFSSL_LIBWEBSOCKETS
#define WOLFSSL_OPENSSH
#define WOLFSSL_QT
#define FORTRESS
#define HAVE_WEBSERVER
#define HAVE_LIGHTY
#define WOLFSSL_NGINX
#define WOLFSSL_HAPROXY
#define HAVE_STUNNEL
#define WOLFSSL_ASIO
#define ASIO_USE_WOLFSSL
#define BOOST_ASIO_USE_WOLFSSL
#define WOLFSSL_OPENVPN
#define NO_WOLFSSL_STUB
#endif
/* TLS static cipher support - off by default */
#if 0
#define WOLFSSL_STATIC_RSA
#define WOLFSSL_STATIC_DH
#define WOLFSSL_STATIC_PSK
#endif
/* TLS sniffer support - off by default */
#if 0
#define WOLFSSL_STATIC_EPHEMERAL
#define WOLFSSL_SNIFFER
#endif
/* Deprecated */
#define NO_DSA
#define NO_MD4
#define NO_MD5
#define NO_OLD_TLS
/* Used to manually test disable edge cases */
#ifdef TEST_DISABLES
#define NO_SESSION_CACHE
//#define NO_ECC256
//#define NO_ECC_KEY_EXPORT
//#define NO_ECC_DHE
//#define NO_ECC_SIGN
//#define NO_ECC_VERIFY
//#define NO_RSA
#define NO_DH
#define NO_SHA
#define NO_SHA256
#ifdef NO_SHA256
#undef WOLFSSL_SHA224
#endif
#define NO_SHA512
#ifdef NO_SHA512
#undef WOLFSSL_SHA384
#undef WOLFSSL_SHA512
#undef HAVE_ED25519
#endif
//#define NO_KDF
//#define NO_HMAC
#define NO_RC4
#define NO_DES3
//#define NO_AES
#define NO_AES_CBC
#define WOLFSSL_NO_SHAKE128
#define NO_PSK
#define NO_PWDBASED
//#define WOLFSSL_NO_TLS12
//#define NO_64BIT
#define WOLFSSL_SP_NO_MALLOC
#define NO_FILESYSTEM
#define NO_WRITEV
#define NO_ERROR_STRINGS
//#define NO_WOLFSSL_CLIENT
//#define NO_WOLFSSL_SERVER
#define NO_MULTIBYTE_PRINT
//#define NO_ASN_TIME
//#define NO_ASN_CRYPT
//#define NO_CODING
#define NO_SIG_WRAPPER
//#define NO_HASH_WRAPPER
//#define WC_NO_HARDEN
//#define NO_CERTS
//#define NO_ASN
#endif
#ifdef __cplusplus
}
#endif
#endif /* WOLFSSL_USER_SETTINGS_H */

597
wrapper/Ada/wolfssl.adb Normal file
View File

@ -0,0 +1,597 @@
with Interfaces.C.Strings;
package body WolfSSL is
subtype size_t is Interfaces.C.size_t; use type size_t;
subtype long is Interfaces.C.long;
function Get_WolfSSL_Success return int with
Convention => C,
External_Name => "get_wolfssl_success",
Import => True;
WOLFSSL_SUCCESS : constant int := Get_WolfSSL_Success;
function Initialize_WolfSSL return int with
Convention => C,
External_Name => "wolfSSL_Init",
Import => True;
function Finalize_WolfSSL return int with
Convention => C,
External_Name => "wolfSSL_Cleanup",
Import => True;
procedure Finalize is
Result : constant int := Finalize_WolfSSL;
begin
if Result /= WOLFSSL_SUCCESS then
raise Cleanup_Error;
end if;
end Finalize;
function WolfTLSv1_2_Server_Method return Method_Type with
Convention => C,
External_Name => "wolfTLSv1_2_server_method",
Import => True;
function TLSv1_2_Server_Method return Method_Type is
begin
return WolfTLSv1_2_Server_Method;
end TLSv1_2_Server_Method;
function WolfTLSv1_3_Server_Method return Method_Type with
Convention => C,
External_Name => "wolfTLSv1_3_server_method",
Import => True;
function TLSv1_3_Server_Method return Method_Type is
begin
return WolfTLSv1_3_Server_Method;
end TLSv1_3_Server_Method;
function WolfSSL_CTX_new (Method : Method_Type)
return Context_Type with
Convention => C, External_Name => "wolfSSL_CTX_new", Import => True;
procedure Create_Context (Method : Method_Type;
Context : out Optional_Context) is
C : constant Context_Type := WolfSSL_CTX_new (Method);
begin
if C = null then
Context := (Exists => False);
else
Context := (Exists => True, Instance => C);
end if;
end Create_Context;
procedure WolfSSL_CTX_free (Context : Context_Type) with
Convention => C, External_Name => "wolfSSL_CTX_free", Import => True;
procedure Free (Context : in out Optional_Context) is
begin
WolfSSL_CTX_free (Context.Instance);
Context := (Exists => False);
end Free;
type Opaque_X509_Store_Context is limited null record;
type X509_Store_Context is access Opaque_X509_Store_Context with
Convention => C;
type Verify_Callback is access function
(A : int;
Context : X509_Store_Context)
return int
with Convention => C;
procedure WolfSSL_CTX_Set_Verify (Context : Context_Type;
Mode : int;
Callback : Verify_Callback) with
Convention => C,
External_Name => "wolfSSL_CTX_set_verify",
Import => True;
-- This function sets the verification method for remote peers and
-- also allows a verify callback to be registered with the SSL
-- context. The verify callback will be called only when a
-- verification failure has occurred. If no verify callback is
-- desired, the NULL pointer can be used for verify_callback.
-- The verification mode of peer certificates is a logically OR'd
-- list of flags. The possible flag values include:
-- SSL_VERIFY_NONE Client mode: the client will not verify the
-- certificate received from the server and the handshake will
-- continue as normal. Server mode: the server will not send a
-- certificate request to the client. As such, client verification
-- will not be enabled. SSL_VERIFY_PEER Client mode: the client will
-- verify the certificate received from the server during the
-- handshake. This is turned on by default in wolfSSL, therefore,
-- using this option has no effect. Server mode: the server will send
-- a certificate request to the client and verify the client
-- certificate received. SSL_VERIFY_FAIL_IF_NO_PEER_CERT Client mode:
-- no effect when used on the client side. Server mode:
-- the verification will fail on the server side if the client fails
-- to send a certificate when requested to do so (when using
-- SSL_VERIFY_PEER on the SSL server).
-- SSL_VERIFY_FAIL_EXCEPT_PSK Client mode: no effect when used on
-- the client side. Server mode: the verification is the same as
-- SSL_VERIFY_FAIL_IF_NO_PEER_CERT except in the case of a
-- PSK connection. If a PSK connection is being made then the
-- connection will go through without a peer cert.
function "&" (Left, Right : Mode_Type) return Mode_Type is
L : constant Unsigned_32 := Unsigned_32 (Left);
R : constant Unsigned_32 := Unsigned_32 (Right);
begin
return Mode_Type (L and R);
end "&";
procedure Set_Verify (Context : Context_Type;
Mode : Mode_Type) is
begin
WolfSSL_CTX_Set_Verify (Context => Context,
Mode => int (Mode),
Callback => null);
end Set_Verify;
function Use_Certificate_File (Context : Context_Type;
File : char_array;
Format : int)
return int with
Convention => C,
External_Name => "wolfSSL_CTX_use_certificate_file",
Import => True;
function Use_Certificate_File (Context : Context_Type;
File : String;
Format : File_Format)
return Subprogram_Result is
C : size_t;
F : char_array (1 .. File'Length + 1);
Result : int;
begin
Interfaces.C.To_C (Item => File,
Target => F,
Count => C,
Append_Nul => True);
Result := Use_Certificate_File (Context, F (1 .. C), int (Format));
if Result = WOLFSSL_SUCCESS then
return Success;
else
return Failure;
end if;
end Use_Certificate_File;
function Use_Certificate_Buffer (Context : Context_Type;
Input : char_array;
Size : long;
Format : int)
return int with
Convention => C,
External_Name => "wolfSSL_CTX_use_certificate_buffer",
Import => True;
function Use_Certificate_Buffer (Context : Context_Type;
Input : char_array;
Format : File_Format)
return Subprogram_Result is
Result : int;
begin
Result := Use_Certificate_Buffer (Context, Input,
Input'Length, int (Format));
if Result = WOLFSSL_SUCCESS then
return Success;
else
return Failure;
end if;
end Use_Certificate_Buffer;
function Use_Private_Key_File (Context : Context_Type;
File : char_array;
Format : int)
return int with
Convention => C,
External_Name => "wolfSSL_CTX_use_PrivateKey_file",
Import => True;
function Use_Private_Key_File (Context : Context_Type;
File : String;
Format : File_Format)
return Subprogram_Result is
C : size_t;
F : char_array (1 .. File'Length + 1);
Result : int;
begin
Interfaces.C.To_C (Item => File,
Target => F,
Count => C,
Append_Nul => True);
Result := Use_Private_Key_File (Context, F (1 .. C), int (Format));
if Result = WOLFSSL_SUCCESS then
return Success;
else
return Failure;
end if;
end Use_Private_Key_File;
function Use_Private_Key_Buffer (Context : Context_Type;
Input : char_array;
Size : long;
Format : int)
return int with
Convention => C,
External_Name => "wolfSSL_CTX_use_PrivateKey_buffer",
Import => True;
function Use_Private_Key_Buffer (Context : Context_Type;
Input : Byte_Array;
Format : File_Format)
return Subprogram_Result is
Result : int;
begin
Result := Use_Private_Key_Buffer (Context, Input,
Input'Length, int (Format));
if Result = WOLFSSL_SUCCESS then
return Success;
else
return Failure;
end if;
end Use_Private_Key_Buffer;
function Load_Verify_Locations1
(Context : Context_Type;
File : char_array;
Path : char_array) return int with
Convention => C,
External_Name => "wolfSSL_CTX_load_verify_locations",
Import => True;
-- This function loads PEM-formatted CA certificate files into
-- the SSL context (WOLFSSL_CTX). These certificates will be treated
-- as trusted root certificates and used to verify certs received
-- from peers during the SSL handshake. The root certificate file,
-- provided by the file argument, may be a single certificate or a
-- file containing multiple certificates. If multiple CA certs are
-- included in the same file, wolfSSL will load them in the same order
-- they are presented in the file. The path argument is a pointer to
-- the name of a directory that contains certificates of trusted
-- root CAs. If the value of file is not NULL, path may be specified
-- as NULL if not needed. If path is specified and NO_WOLFSSL_DIR was
-- not defined when building the library, wolfSSL will load all
-- CA certificates located in the given directory. This function will
-- attempt to load all files in the directory. This function expects
-- PEM formatted CERT_TYPE file with header "--BEGIN CERTIFICATE--".
subtype char_array_ptr is Interfaces.C.Strings.char_array_access;
function Load_Verify_Locations2
(Context : Context_Type;
File : char_array;
Path : char_array_ptr) return int with
Convention => C,
External_Name => "wolfSSL_CTX_load_verify_locations",
Import => True;
function Load_Verify_Locations3
(Context : Context_Type;
File : char_array_ptr;
Path : char_array) return int with
Convention => C,
External_Name => "wolfSSL_CTX_load_verify_locations",
Import => True;
function Load_Verify_Locations4
(Context : Context_Type;
File : char_array_ptr;
Path : char_array_ptr) return int with
Convention => C,
External_Name => "wolfSSL_CTX_load_verify_locations",
Import => True;
function Load_Verify_Locations (Context : Context_Type;
File : String;
Path : String)
return Subprogram_Result is
FC : size_t; -- File Count, specifies the characters used in F.
F : aliased char_array := (1 .. File'Length + 1 => '#');
PC : size_t; -- Path Count, specifies the characters used in P.
P : aliased char_array := (1 .. Path'Length + 1 => '#');
Result : int;
begin
if File = "" then
if Path = "" then
Result := Load_Verify_Locations4 (Context, null, null);
else
Interfaces.C.To_C (Item => Path,
Target => P,
Count => PC,
Append_Nul => True);
Result := Load_Verify_Locations3 (Context, null, P);
end if;
else
Interfaces.C.To_C (Item => File,
Target => F,
Count => FC,
Append_Nul => True);
if Path = "" then
Result := Load_Verify_Locations2 (Context, F, null);
else
Interfaces.C.To_C (Item => Path,
Target => P,
Count => PC,
Append_Nul => True);
Interfaces.C.To_C (Item => Path,
Target => P,
Count => PC,
Append_Nul => True);
Result := Load_Verify_Locations1 (Context, F, P);
end if;
end if;
if Result = WOLFSSL_SUCCESS then
return Success;
else
return Failure;
end if;
end Load_Verify_Locations;
function Load_Verify_Buffer1
(Context : Context_Type;
Input : char_array;
Size : int;
Format : int) return int with
Convention => C,
External_Name => "wolfSSL_CTX_load_verify_buffer",
Import => True;
-- This function loads a CA certificate buffer into the WOLFSSL
-- Context. It behaves like the non-buffered version, only differing
-- in its ability to be called with a buffer as input instead of
-- a file. The buffer is provided by the in argument of size sz.
-- format specifies the format type of the buffer; SSL_FILETYPE_ASN1
-- or SSL_FILETYPE_PEM. More than one CA certificate may be loaded
-- per buffer as long as the format is in PEM. Please see
-- the examples for proper usage.
function Load_Verify_Buffer (Context : Context_Type;
Input : Byte_Array;
Format : File_Format)
return Subprogram_Result is
Result : int;
begin
Result := Load_Verify_Buffer1 (Context => Context,
Input => Input,
Size => Input'Length,
Format => int(Format));
if Result = WOLFSSL_SUCCESS then
return Success;
else
return Failure;
end if;
end Load_Verify_Buffer;
function WolfSSL_New (Context : Context_Type)
return WolfSSL_Type with
Convention => C,
External_Name => "wolfSSL_new",
Import => True;
procedure Create_WolfSSL (Context : Context_Type;
Ssl : out Optional_WolfSSL) is
Result : WolfSSL_Type := WolfSSL_New (Context);
begin
if Result /= null then
Ssl := (Exists => True,
Instance => Result);
else
Ssl := (Exists => False);
end if;
end Create_WolfSSL;
function WolfSSL_Set_Fd (Ssl : WolfSSL_Type; Fd : int) return int with
Convention => C,
External_Name => "wolfSSL_set_fd",
Import => True;
function Attach (Ssl : WolfSSL_Type;
Socket : Integer)
return Subprogram_Result is
Result : int := WolfSSL_Set_Fd (Ssl, int (Socket));
begin
if Result = WOLFSSL_SUCCESS then
return Success;
else
return Failure;
end if;
end Attach;
procedure WolfSSL_Keep_Arrays (Ssl : WolfSSL_Type) with
Convention => C,
External_Name => "wolfSSL_KeepArrays",
Import => True;
procedure Keep_Arrays (Ssl : WolfSSL_Type) is
begin
WolfSSL_Keep_Arrays (Ssl);
end Keep_Arrays;
function WolfSSL_Accept (Ssl : WolfSSL_Type) return int with
Convention => C,
External_Name => "wolfSSL_accept",
Import => True;
function Accept_Connection (Ssl : WolfSSL_Type)
return Subprogram_Result is
Result : int := WolfSSL_Accept (Ssl);
begin
if Result = WOLFSSL_SUCCESS then
return Success;
else
return Failure;
end if;
end Accept_Connection;
procedure WolfSSL_Free_Arrays (Ssl : WolfSSL_Type) with
Convention => C,
External_Name => "wolfSSL_FreeArrays",
Import => True;
procedure Free_Arrays (Ssl : WolfSSL_Type) is
begin
WolfSSL_Free_Arrays (Ssl);
end Free_Arrays;
function WolfSSL_Read (Ssl : WolfSSL_Type;
Data : out char_array;
Sz : int) return int with
Convention => C,
External_Name => "wolfSSL_read",
Import => True;
-- This function reads sz bytes from the SSL session (ssl) internal
-- read buffer into the buffer data. The bytes read are removed from
-- the internal receive buffer. If necessary wolfSSL_read() will
-- negotiate an SSL/TLS session if the handshake has not already
-- been performed yet by wolfSSL_connect() or wolfSSL_accept().
-- The SSL/TLS protocol uses SSL records which have a maximum size
-- of 16kB (the max record size can be controlled by the
-- MAX_RECORD_SIZE define in /wolfssl/internal.h). As such, wolfSSL
-- needs to read an entire SSL record internally before it is able
-- to process and decrypt the record. Because of this, a call to
-- wolfSSL_read() will only be able to return the maximum buffer
-- size which has been decrypted at the time of calling. There may
-- be additional not-yet-decrypted data waiting in the internal
-- wolfSSL receive buffer which will be retrieved and decrypted with
-- the next call to wolfSSL_read(). If sz is larger than the number
-- of bytes in the internal read buffer, SSL_read() will return
-- the bytes available in the internal read buffer. If no bytes are
-- buffered in the internal read buffer yet, a call to wolfSSL_read()
-- will trigger processing of the next record.
--
-- The integer returned is the number of bytes read upon success.
-- 0 will be returned upon failure. This may be caused by a either
-- a clean (close notify alert) shutdown or just that the peer closed
-- the connection. Call wolfSSL_get_error() for the specific
-- error code. SSL_FATAL_ERROR will be returned upon failure when
-- either an error occurred or, when using non-blocking sockets,
-- the SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE error was received
-- and and the application needs to call wolfSSL_read() again.
-- Use wolfSSL_get_error() to get a specific error code.
function Read (Ssl : WolfSSL_Type) return Read_Result is
Data : char_array (1 .. Byte_Index'Last);
Size : int;
begin
Size := WolfSSL_Read (Ssl, Data, int (Byte_Index'Last));
if Size < 0 then
return (Result => Failure, Last => 0);
else
return (Result => Success,
Last => Byte_Index (Size),
Buffer => Data (1 .. Byte_Index (Size)));
end if;
end Read;
function WolfSSL_Write (Ssl : WolfSSL_Type;
Data : char_array;
Sz : int) return int with
Convention => C,
External_Name => "wolfSSL_write",
Import => True;
function Write (Ssl : WolfSSL_Type;
Data : Byte_Array) return Integer is
Size : constant int := Data'Length;
Result : int;
begin
Result := WolfSSL_Write (Ssl, Data, Size);
return Integer (Result);
end Write;
function WolfSSL_Shutdown (Ssl : WolfSSL_Type) return int with
Convention => C,
External_Name => "wolfSSL_shutdown",
Import => True;
-- This function shuts down an active SSL/TLS connection using
-- the SSL session, ssl. This function will try to send a
-- "close notify" alert to the peer. The calling application can
-- choose to wait for the peer to send its "close notify" alert
-- in response or just go ahead and shut down the underlying
-- connection after directly calling wolfSSL_shutdown (to save
-- resources). Either option is allowed by the TLS specification.
-- If the underlying connection will be used again in the future,
-- the complete two_directional shutdown procedure must be performed
-- to keep synchronization intact between the peers.
-- wolfSSL_shutdown() works with both blocking and non_blocking I/O.
-- When the underlying I/O is non_blocking, wolfSSL_shutdown() will
-- return an error if the underlying I/O could not satisfy the needs
-- of wolfSSL_shutdown() to continue. In this case, a call to
-- wolfSSL_get_error() will yield either SSL_ERROR_WANT_READ or
-- SSL_ERROR_WANT_WRITE. The calling process must then repeat
-- the call to wolfSSL_shutdown() when the underlying I/O is ready.
function Shutdown (Ssl : WolfSSL_Type) return Subprogram_Result is
Result : constant int := WolfSSL_Shutdown (Ssl);
begin
if Result = WOLFSSL_SUCCESS then
return Success;
else
return Failure;
end if;
end Shutdown;
function WolfSSL_Connect (Ssl : WolfSSL_Type) return int with
Convention => C,
External_Name => "wolfSSL_connect",
Import => True;
-- This function is called on the client side and initiates
-- an SSL/TLS handshake with a server. When this function is called,
-- the underlying communication channel has already been set up.
-- wolfSSL_connect() works with both blocking and non_blocking I/O.
-- When the underlying I/O is non_blocking, wolfSSL_connect() will
-- return when the underlying I/O could not satisfy the needs
-- of wolfSSL_connect to continue the handshake. In this case,
-- a call to wolfSSL_get_error() will yield either
-- SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE. The calling process
-- must then repeat the call to wolfSSL_connect() when
-- the underlying I/O is ready and wolfSSL will pick up where
-- it left off. When using a non_blocking socket, nothing needs
-- to be done, but select() can be used to check for the required
-- condition. If the underlying I/O is blocking, wolfSSL_connect()
-- will only return once the handshake has been finished or an error
-- occurred. wolfSSL takes a different approach to certificate
-- verification than OpenSSL does. The default policy for the client
-- is to verify the server, this means that if you don't load CAs
-- to verify the server you'll get a connect error,
-- unable to verify (_155). It you want to mimic OpenSSL behavior
-- of having SSL_connect succeed even if verifying the server fails
-- and reducing security you can do this by calling:
-- SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0); before calling
-- SSL_new(); Though it's not recommended.
function Connect (Ssl : WolfSSL_Type) return Subprogram_Result is
Result : constant int := WolfSSL_Connect (Ssl);
begin
if Result = WOLFSSL_SUCCESS then
return Success;
else
return Failure;
end if;
end Connect;
procedure WolfSSL_Free (Ssl : WolfSSL_Type) with
Convention => C,
External_Name => "wolfSSL_free",
Import => True;
procedure Free (Ssl : in out Optional_WolfSSL) is
begin
if Ssl.Exists then
WolfSSL_Free (Ssl.Instance);
end if;
Ssl := (Exists => False);
end Free;
Result : constant int := Initialize_WolfSSL;
begin
if Result /= WOLFSSL_SUCCESS then
raise Initialization_Error;
end if;
end WolfSSL;

262
wrapper/Ada/wolfssl.ads Normal file
View File

@ -0,0 +1,262 @@
with Interfaces.C;
-- This package is annotated "with SPARK_Mode" that SPARK can verify
-- the API of this package is used correctly. The body of this package
-- cannot be formally verified since it calls C functions and uses
-- access-to-object types which are not part of the SPARK subset of
-- the Ada programming language.
package WolfSSL with SPARK_Mode is
procedure Finalize;
-- Must be called before application exit.
Initialization_Error : exception;
-- Raised if error was encountered during initialization of the
-- WolfSSL library. The WolfSSL libray is initialized during
-- elaboration time.
Cleanup_Error : exception;
-- Raised if error was encountered during application shutdown
-- and cleanup of resources allocated by WolfSSL has failed.
subtype char_array is Interfaces.C.char_array; -- Remove?
subtype Byte_Index is Interfaces.C.size_t range 0 .. 16_000;
subtype Byte_Array is Interfaces.C.char_array;
type Subprogram_Result is (Success, Failure);
type Context_Type is limited private;
type Optional_Context (Exists : Boolean := False) is record
case Exists is
when True => Instance : Context_Type;
when False => null;
end case;
end record;
type Method_Type is limited private;
function TLSv1_2_Server_Method return Method_Type;
function TLSv1_3_Server_Method return Method_Type;
procedure Create_Context (Method : Method_Type;
Context : out Optional_Context);
-- Create and initialize a WolfSSL context.
procedure Free (Context : in out Optional_Context) with
Pre => Context.Exists,
Post => not Context.Exists;
type Mode_Type is private;
function "&" (Left, Right : Mode_Type) return Mode_Type;
Verify_None : constant Mode_Type;
Verify_Peer : constant Mode_Type;
Verify_Fail_If_No_Peer_Cert : constant Mode_Type;
Verify_Client_Once : constant Mode_Type;
Verify_Post_Handshake : constant Mode_Type;
Verify_Fail_Except_Psk : constant Mode_Type;
Verify_Default : constant Mode_Type;
procedure Set_Verify (Context : Context_Type;
Mode : Mode_Type);
type File_Format is private;
Format_Asn1 : constant File_Format;
Format_Pem : constant File_Format;
Format_Default : constant File_Format;
function Use_Certificate_File (Context : Context_Type;
File : String;
Format : File_Format)
return Subprogram_Result;
function Use_Certificate_Buffer (Context : Context_Type;
Input : char_array;
Format : File_Format)
return Subprogram_Result;
function Use_Private_Key_File (Context : Context_Type;
File : String;
Format : File_Format)
return Subprogram_Result;
function Use_Private_Key_Buffer (Context : Context_Type;
Input : Byte_Array;
Format : File_Format)
return Subprogram_Result;
function Load_Verify_Locations (Context : Context_Type;
File : String;
Path : String)
return Subprogram_Result;
function Load_Verify_Buffer (Context : Context_Type;
Input : Byte_Array;
Format : File_Format)
return Subprogram_Result;
type WolfSSL_Type is limited private;
type Optional_WolfSSL (Exists : Boolean := False) is record
case Exists is
when True => Instance : WolfSSL_Type;
when False => null;
end case;
end record;
procedure Create_WolfSSL (Context : Context_Type;
Ssl : out Optional_WolfSSL);
-- Attach wolfSSL to the socket.
function Attach (Ssl : WolfSSL_Type;
Socket : Integer)
return Subprogram_Result;
procedure Keep_Arrays (Ssl : WolfSSL_Type);
-- Don't free temporary arrays at end of handshake.
procedure Free_Arrays (Ssl : WolfSSL_Type);
-- User doesn't need temporary arrays anymore, Free.
function Accept_Connection (Ssl : WolfSSL_Type)
return Subprogram_Result;
-- This record type has discriminants with default values to be able
-- to compile this code under the restriction no secondary stack.
type Read_Result (Result : Subprogram_Result := Failure;
Last : Byte_Index := Byte_Index'Last) is record
case Result is
when Success => Buffer : Byte_Array (1 .. Last);
when Failure => null;
end case;
end record;
function Read (Ssl : WolfSSL_Type) return Read_Result;
-- The number of bytes written is returned.
function Write (Ssl : WolfSSL_Type; Data : Byte_Array) return Integer;
function Shutdown (Ssl : WolfSSL_Type) return Subprogram_Result;
procedure Free (Ssl : in out Optional_WolfSSL) with
Pre => Ssl.Exists,
Post => not Ssl.Exists;
function Connect (Ssl : WolfSSL_Type) return Subprogram_Result;
private
pragma SPARK_Mode (Off);
subtype int is Interfaces.C.int; use type int;
type Opaque_Method is limited null record;
type Opaque_Context is limited null record;
type Opaque_WolfSSL is limited null record;
-- Access-to-object types with convention C uses the same amount of
-- memory for storing pointers as is done in the C programming
-- language. The following access type definitions are used in
-- the Ada binding to the WolfSSL library:
type Context_Type is access Opaque_Context with Convention => C;
type Method_Type is access Opaque_Method with Convention => C;
type WolfSSL_Type is access Opaque_WolfSSL with Convention => C;
subtype Unsigned_32 is Interfaces.Unsigned_32; use type Unsigned_32;
type Mode_Type is new Unsigned_32;
-- The following imported subprograms are used to initialize
-- the constants defined in the public part of this package
-- specification. They cannot therefore be moved to the body
-- of this package.
function WolfSSL_Verify_None return int with
Convention => C,
External_Name => "get_wolfssl_verify_none",
Import => True;
function WolfSSL_Verify_Peer return int with
Convention => C,
External_Name => "get_wolfssl_verify_peer",
Import => True;
function WolfSSL_Verify_Fail_If_No_Peer_Cert return int with
Convention => C,
External_Name => "get_wolfssl_verify_fail_if_no_peer_cert",
Import => True;
function WolfSSL_Verify_Client_Once return int with
Convention => C,
External_Name => "get_wolfssl_verify_client_once",
Import => True;
function WolfSSL_Verify_Post_Handshake return int with
Convention => C,
External_Name => "get_wolfssl_verify_post_handshake",
Import => True;
function WolfSSL_Verify_Fail_Except_Psk return int with
Convention => C,
External_Name => "get_wolfssl_verify_fail_except_psk",
Import => True;
function WolfSSL_Verify_Default return int with
Convention => C,
External_Name => "get_wolfssl_verify_default",
Import => True;
Verify_None : constant Mode_Type := Mode_Type (WolfSSL_Verify_None);
Verify_Peer : constant Mode_Type := Mode_Type (WolfSSL_Verify_Peer);
Verify_Fail_If_No_Peer_Cert : constant Mode_Type :=
Mode_Type (WolfSSL_Verify_Fail_If_No_Peer_Cert);
Verify_Client_Once : constant Mode_Type :=
Mode_Type (WolfSSL_Verify_Client_Once);
Verify_Post_Handshake : constant Mode_Type :=
Mode_Type (WolfSSL_Verify_Post_Handshake);
Verify_Fail_Except_Psk : constant Mode_Type :=
Mode_Type (WolfSSL_Verify_Fail_Except_Psk);
Verify_Default : constant Mode_Type :=
Mode_Type (WolfSSL_Verify_Default);
type File_Format is new Unsigned_32;
function WolfSSL_Filetype_Asn1 return int with
Convention => C,
External_Name => "get_wolfssl_filetype_asn1",
Import => True;
function WolfSSL_Filetype_Pem return int with
Convention => C,
External_Name => "get_wolfssl_filetype_pem",
Import => True;
function WolfSSL_Filetype_Default return int with
Convention => C,
External_Name => "get_wolfssl_filetype_default",
Import => True;
Format_Asn1 : constant File_Format :=
File_Format (WolfSSL_Filetype_Asn1);
Format_Pem : constant File_Format :=
File_Format (WolfSSL_Filetype_Pem);
Format_Default : constant File_Format :=
File_Format (WolfSSL_Filetype_Default);
end WolfSSL;

View File

@ -2,6 +2,7 @@
# included from Top Level Makefile.am
# All paths should be given relative to the root
include wrapper/Ada/include.am
include wrapper/CSharp/include.am
EXTRA_DIST+= wrapper/python/README.md