mirror of
https://github.com/Alcaro/Flips.git
synced 2026-09-08 10:35:11 -05:00
Initial commit
This commit is contained in:
34375
arlib/socket/libtomcrypt.c
Normal file
34375
arlib/socket/libtomcrypt.c
Normal file
File diff suppressed because it is too large
Load Diff
64
arlib/socket/shitty-server.cpp
Normal file
64
arlib/socket/shitty-server.cpp
Normal file
@@ -0,0 +1,64 @@
|
||||
#ifdef ARLIB_TEST_SERVER
|
||||
//Shitty Server: a buggy echo server
|
||||
//after the first 32 bytes, it drops your connection on the floor, without FIN or anything
|
||||
//probably somewhat useful to test resilience against network failure
|
||||
//it would be more useful to make it ignore the pings too, but I can't do that without fiddling with the firewall, and I'd rather not
|
||||
|
||||
//linux and root only because TCP_REPAIR requires that
|
||||
//http://oroboro.com/dealing-with-network-port-abuse-in-sockets-in-c
|
||||
//if you need to test a windows program against dropped sockets, run this on another machine, possibly a virtual machine
|
||||
|
||||
//most of the code stolen from http://www.thegeekstuff.com/2011/12/c-socket-programming/ because I'm lazy
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
int listenfd = 0, connfd = 0;
|
||||
struct sockaddr_in serv_addr;
|
||||
|
||||
char sendBuff[1025];
|
||||
time_t ticks;
|
||||
|
||||
listenfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
memset(&serv_addr, '0', sizeof(serv_addr));
|
||||
memset(sendBuff, '0', sizeof(sendBuff));
|
||||
|
||||
serv_addr.sin_family = AF_INET;
|
||||
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
serv_addr.sin_port = htons(168);
|
||||
|
||||
bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
|
||||
perror("bind");
|
||||
|
||||
listen(listenfd, 10);
|
||||
perror("listen");
|
||||
|
||||
while(1)
|
||||
{
|
||||
connfd = accept(listenfd, (struct sockaddr*)NULL, NULL);
|
||||
perror("accept");
|
||||
|
||||
memset(sendBuff, 0, 32);
|
||||
read(connfd, sendBuff, 32);
|
||||
write(connfd, sendBuff, 32);
|
||||
sleep(1); // otherwise the ACK gives a RST
|
||||
|
||||
int yes = 1;
|
||||
setsockopt(connfd, SOL_TCP, TCP_REPAIR, &yes, sizeof(yes));
|
||||
perror("TCP_REPAIR");
|
||||
|
||||
close(connfd);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
342
arlib/socket/socket-openssl.cpp
Normal file
342
arlib/socket/socket-openssl.cpp
Normal file
@@ -0,0 +1,342 @@
|
||||
#include "socket.h"
|
||||
|
||||
#ifdef ARLIB_SSL_OPENSSL
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/x509v3.h>
|
||||
|
||||
static SSL_CTX * ctx;
|
||||
|
||||
static void initialize()
|
||||
{
|
||||
static bool initialized = false;
|
||||
if (initialized) return;
|
||||
initialized = true;
|
||||
//SSL_load_error_strings(); // TODO
|
||||
SSL_library_init();
|
||||
ctx = SSL_CTX_new(SSLv23_client_method());
|
||||
SSL_CTX_set_default_verify_paths(ctx);
|
||||
SSL_CTX_set_cipher_list(ctx, "HIGH:!DSS:!aNULL@STRENGTH");
|
||||
}
|
||||
|
||||
static bool validate_hostname(const char *hostname, const X509 *server_cert);
|
||||
|
||||
class socketssl_impl : public socketssl {
|
||||
public:
|
||||
socket* sock;
|
||||
SSL* ssl;
|
||||
//bool nonblock;
|
||||
|
||||
static socketssl_impl* create(socket* parent, const char * domain, bool permissive)
|
||||
{
|
||||
if (!parent) return NULL;
|
||||
|
||||
socketssl_impl* ret = new socketssl_impl();
|
||||
ret->sock = parent;
|
||||
ret->fd = parent->get_fd();
|
||||
ret->ssl = SSL_new(ctx);
|
||||
//ret->nonblock = false;
|
||||
SSL_set_fd(ret->ssl, ret->fd);
|
||||
//TODO: set fd to nonblock
|
||||
|
||||
if (!permissive)
|
||||
{
|
||||
SSL_set_verify(ret->ssl, SSL_VERIFY_PEER, NULL);
|
||||
}
|
||||
|
||||
//plausible cert failure cases: unrooted (including self-signed), expired, wrong domain
|
||||
//permissive should allow the former two, but still block the third
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10100000 // >= 1.1.0
|
||||
#error test, especially set0 vs set1
|
||||
SSL_set1_host(ssl, "example.com");
|
||||
#endif
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000 && OPENSSL_VERSION_NUMBER < 0x10100000 // >= 1.0.2, < 1.1.0
|
||||
#error test, especially [gs]et0 vs [gs]et1
|
||||
X509_VERIFY_PARAM* param = SSL_get0_param(ssl);
|
||||
//optional?
|
||||
//X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
|
||||
X509_VERIFY_PARAM_set1_host(param, "example.com", 0);
|
||||
#endif
|
||||
|
||||
bool ok = (SSL_connect(ret->ssl)==1);
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10002000 // < 1.0.2
|
||||
if (ok && !validate_hostname(domain, SSL_get_peer_certificate(ret->ssl)))
|
||||
{
|
||||
ok=false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
delete ret;
|
||||
return 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*private*/ int fixret(int ret)
|
||||
{
|
||||
if (ret > 0) return ret;
|
||||
|
||||
int sslerror = SSL_get_error(ssl, ret);
|
||||
if (sslerror==SSL_ERROR_WANT_READ || sslerror==SSL_ERROR_WANT_WRITE) return 0;
|
||||
//printf("ERR=%i\n",sslerror);
|
||||
//ERR_print_errors();
|
||||
return e_ssl_failure;
|
||||
}
|
||||
|
||||
//only supports nonblocking
|
||||
int recv(uint8_t* data, unsigned int len, bool block = false)
|
||||
{
|
||||
return fixret(SSL_read(ssl, data, len));
|
||||
}
|
||||
|
||||
int sendp(const uint8_t* data, unsigned int len, bool block = true)
|
||||
{
|
||||
return fixret(SSL_write(ssl, data, len));
|
||||
}
|
||||
|
||||
~socketssl_impl()
|
||||
{
|
||||
SSL_shutdown(ssl);
|
||||
SSL_free(ssl);
|
||||
delete sock;
|
||||
}
|
||||
};
|
||||
|
||||
socketssl* socketssl::create(socket* parent, const char * domain, bool permissive)
|
||||
{
|
||||
initialize();
|
||||
if (!ctx) return NULL;
|
||||
|
||||
return socketssl_impl::create(parent, domain, permissive);
|
||||
}
|
||||
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10002000
|
||||
//from TLSe https://github.com/eduardsui/tlse/blob/90bdc5d/tlse.c#L2519
|
||||
#define bad_certificate -1
|
||||
static int tls_certificate_valid_subject_name(const unsigned char *cert_subject, const char *subject) {
|
||||
// no subjects ...
|
||||
if (((!cert_subject) || (!cert_subject[0])) && ((!subject) || (!subject[0])))
|
||||
return 0;
|
||||
|
||||
if ((!subject) || (!subject[0]))
|
||||
return bad_certificate;
|
||||
|
||||
if ((!cert_subject) || (!cert_subject[0]))
|
||||
return bad_certificate;
|
||||
|
||||
// exact match
|
||||
if (!strcmp((const char *)cert_subject, subject))
|
||||
return 0;
|
||||
|
||||
const char *wildcard = strchr((const char *)cert_subject, '*');
|
||||
if (wildcard) {
|
||||
// 6.4.3 (1) The client SHOULD NOT attempt to match a presented identifier in
|
||||
// which the wildcard character comprises a label other than the left-most label
|
||||
if (!wildcard[1]) {
|
||||
// subject is [*]
|
||||
// or
|
||||
// subject is [something*] .. invalid
|
||||
return bad_certificate;
|
||||
}
|
||||
wildcard++;
|
||||
const char *match = strstr(subject, wildcard);
|
||||
if ((!match) && (wildcard[0] == '.')) {
|
||||
// check *.domain.com agains domain.com
|
||||
wildcard++;
|
||||
if (!strcasecmp(subject, wildcard))
|
||||
return 0;
|
||||
}
|
||||
if (match) {
|
||||
unsigned long offset = (unsigned long)match - (unsigned long)subject;
|
||||
if (offset) {
|
||||
// check for foo.*.domain.com against *.domain.com (invalid)
|
||||
if (memchr(subject, '.', offset))
|
||||
return bad_certificate;
|
||||
}
|
||||
// check if exact match
|
||||
if (!strcasecmp(match, wildcard))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return bad_certificate;
|
||||
}
|
||||
|
||||
//copypasted from https://wiki.openssl.org/index.php/Hostname_validation
|
||||
//and modified a bit (for example to add a missing cast)
|
||||
/*
|
||||
Copyright (C) 2012, iSEC Partners.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Helper functions to perform basic hostname validation using OpenSSL.
|
||||
*
|
||||
* Please read "everything-you-wanted-to-know-about-openssl.pdf" before
|
||||
* attempting to use this code. This whitepaper describes how the code works,
|
||||
* how it should be used, and what its limitations are.
|
||||
*
|
||||
* Author: Alban Diquet
|
||||
* License: See LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
// Get rid of OSX 10.7 and greater deprecation warnings.
|
||||
#if defined(__APPLE__) && defined(__clang__)
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
|
||||
//#include <openssl/ssl.h>
|
||||
|
||||
//#include "openssl_hostname_validation.h"
|
||||
//#include "hostcheck.h"
|
||||
|
||||
#define HOSTNAME_MAX_SIZE 255
|
||||
enum HostnameValidationResult { Error, MalformedCertificate, NoSANPresent, MatchFound, MatchNotFound };
|
||||
|
||||
/**
|
||||
* Tries to find a match for hostname in the certificate's Common Name field.
|
||||
*
|
||||
* Returns MatchFound if a match was found.
|
||||
* Returns MatchNotFound if no matches were found.
|
||||
* Returns MalformedCertificate if the Common Name had a NUL character embedded in it.
|
||||
* Returns Error if the Common Name could not be extracted.
|
||||
*/
|
||||
static HostnameValidationResult matches_common_name(const char *hostname, const X509 *server_cert) {
|
||||
int common_name_loc = -1;
|
||||
X509_NAME_ENTRY *common_name_entry = NULL;
|
||||
ASN1_STRING *common_name_asn1 = NULL;
|
||||
char *common_name_str = NULL;
|
||||
|
||||
// Find the position of the CN field in the Subject field of the certificate
|
||||
common_name_loc = X509_NAME_get_index_by_NID(X509_get_subject_name((X509 *) server_cert), NID_commonName, -1);
|
||||
if (common_name_loc < 0) {
|
||||
return Error;
|
||||
}
|
||||
|
||||
// Extract the CN field
|
||||
common_name_entry = X509_NAME_get_entry(X509_get_subject_name((X509 *) server_cert), common_name_loc);
|
||||
if (common_name_entry == NULL) {
|
||||
return Error;
|
||||
}
|
||||
|
||||
// Convert the CN field to a C string
|
||||
common_name_asn1 = X509_NAME_ENTRY_get_data(common_name_entry);
|
||||
if (common_name_asn1 == NULL) {
|
||||
return Error;
|
||||
}
|
||||
common_name_str = (char *) ASN1_STRING_data(common_name_asn1);
|
||||
|
||||
// Make sure there isn't an embedded NUL character in the CN
|
||||
if ((size_t)ASN1_STRING_length(common_name_asn1) != strlen(common_name_str)) {
|
||||
return MalformedCertificate;
|
||||
}
|
||||
|
||||
// Compare expected hostname with the CN
|
||||
if (tls_certificate_valid_subject_name((uint8_t*)common_name_str, hostname)==0) {
|
||||
return MatchFound;
|
||||
}
|
||||
else {
|
||||
return MatchNotFound;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tries to find a match for hostname in the certificate's Subject Alternative Name extension.
|
||||
*
|
||||
* Returns MatchFound if a match was found.
|
||||
* Returns MatchNotFound if no matches were found.
|
||||
* Returns MalformedCertificate if any of the hostnames had a NUL character embedded in it.
|
||||
* Returns NoSANPresent if the SAN extension was not present in the certificate.
|
||||
*/
|
||||
static HostnameValidationResult matches_subject_alternative_name(const char *hostname, const X509 *server_cert) {
|
||||
HostnameValidationResult result = MatchNotFound;
|
||||
int i;
|
||||
int san_names_nb = -1;
|
||||
STACK_OF(GENERAL_NAME) *san_names = NULL;
|
||||
|
||||
// Try to extract the names within the SAN extension from the certificate
|
||||
san_names = (STACK_OF(GENERAL_NAME)*)X509_get_ext_d2i((X509 *) server_cert, NID_subject_alt_name, NULL, NULL);
|
||||
if (san_names == NULL) {
|
||||
return NoSANPresent;
|
||||
}
|
||||
san_names_nb = sk_GENERAL_NAME_num(san_names);
|
||||
|
||||
// Check each name within the extension
|
||||
for (i=0; i<san_names_nb; i++) {
|
||||
const GENERAL_NAME *current_name = sk_GENERAL_NAME_value(san_names, i);
|
||||
|
||||
if (current_name->type == GEN_DNS) {
|
||||
// Current name is a DNS name, let's check it
|
||||
char *dns_name = (char *) ASN1_STRING_data(current_name->d.dNSName);
|
||||
|
||||
// Make sure there isn't an embedded NUL character in the DNS name
|
||||
if ((size_t)ASN1_STRING_length(current_name->d.dNSName) != strlen(dns_name)) {
|
||||
result = MalformedCertificate;
|
||||
break;
|
||||
}
|
||||
else { // Compare expected hostname with the DNS name
|
||||
if (tls_certificate_valid_subject_name((uint8_t*)dns_name, hostname)==0) {
|
||||
result = MatchFound;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sk_GENERAL_NAME_pop_free(san_names, GENERAL_NAME_free);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validates the server's identity by looking for the expected hostname in the
|
||||
* server's certificate. As described in RFC 6125, it first tries to find a match
|
||||
* in the Subject Alternative Name extension. If the extension is not present in
|
||||
* the certificate, it checks the Common Name instead.
|
||||
*
|
||||
* Returns MatchFound if a match was found.
|
||||
* Returns MatchNotFound if no matches were found.
|
||||
* Returns MalformedCertificate if any of the hostnames had a NUL character embedded in it.
|
||||
* Returns Error if there was an error.
|
||||
*/
|
||||
static bool validate_hostname(const char *hostname, const X509 *server_cert) {
|
||||
HostnameValidationResult result;
|
||||
|
||||
if((hostname == NULL) || (server_cert == NULL))
|
||||
return false;
|
||||
|
||||
// First try the Subject Alternative Names extension
|
||||
result = matches_subject_alternative_name(hostname, server_cert);
|
||||
if (result == NoSANPresent) {
|
||||
// Extension was not found: try the Common Name
|
||||
result = matches_common_name(hostname, server_cert);
|
||||
}
|
||||
|
||||
return (result==MatchFound);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
339
arlib/socket/socket-schannel.cpp
Normal file
339
arlib/socket/socket-schannel.cpp
Normal file
@@ -0,0 +1,339 @@
|
||||
#include "socket.h"
|
||||
|
||||
//based on http://wayback.archive.org/web/20100528130307/http://www.coastrd.com/c-schannel-smtp
|
||||
//but heavily rewritten for stability and compactness
|
||||
|
||||
#ifdef ARLIB_SSL_SCHANNEL
|
||||
#ifndef _WIN32
|
||||
#error SChannel only exists on Windows
|
||||
#endif
|
||||
|
||||
#define SECURITY_WIN32
|
||||
#undef bind
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <windows.h>
|
||||
#include <winsock.h>
|
||||
#include <wincrypt.h>
|
||||
#include <wintrust.h>
|
||||
#include <schannel.h>
|
||||
#include <security.h>
|
||||
#include <sspi.h>
|
||||
|
||||
namespace {
|
||||
|
||||
static SecurityFunctionTable* SSPI;
|
||||
static CredHandle cred;
|
||||
|
||||
#define SSPIFlags \
|
||||
(ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT | ISC_REQ_CONFIDENTIALITY | \
|
||||
ISC_RET_EXTENDED_ERROR | ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_STREAM)
|
||||
|
||||
//my mingw headers are outdated
|
||||
#ifndef SCH_USE_STRONG_CRYPTO
|
||||
#define SCH_USE_STRONG_CRYPTO 0x00400000
|
||||
#endif
|
||||
#ifndef SP_PROT_TLS1_2_CLIENT
|
||||
#define SP_PROT_TLS1_2_CLIENT 0x00000800
|
||||
#endif
|
||||
#ifndef SEC_Entry
|
||||
#define SEC_Entry WINAPI
|
||||
#endif
|
||||
|
||||
static void initialize()
|
||||
{
|
||||
if (SSPI) return;
|
||||
|
||||
//linking a DLL is easy, but when there's only one exported function, spending the extra effort is worth it
|
||||
HMODULE secur32 = LoadLibraryA("secur32.dll");
|
||||
typedef PSecurityFunctionTableA SEC_Entry (*InitSecurityInterfaceA_t)(void);
|
||||
InitSecurityInterfaceA_t InitSecurityInterfaceA = (InitSecurityInterfaceA_t)GetProcAddress(secur32, SECURITY_ENTRYPOINT_ANSIA);
|
||||
SSPI = InitSecurityInterfaceA();
|
||||
|
||||
SCHANNEL_CRED SchannelCred = {};
|
||||
SchannelCred.dwVersion = SCHANNEL_CRED_VERSION;
|
||||
SchannelCred.dwFlags = SCH_CRED_NO_DEFAULT_CREDS | SCH_USE_STRONG_CRYPTO;
|
||||
// fun fact: IE11 doesn't use SCH_USE_STRONG_CRYPTO. I guess it favors accepting outdated servers over rejecting evil ones.
|
||||
SchannelCred.grbitEnabledProtocols = SP_PROT_TLS1_2_CLIENT; // Microsoft recommends setting this to zero, but that makes it use TLS 1.0, which sucks.
|
||||
//howsmyssl expects session ticket support for the Good rating, but that's only supported on windows 8, according to
|
||||
// https://connect.microsoft.com/IE/feedback/details/997136/internet-explorer-11-on-windows-7-does-not-support-tls-session-tickets
|
||||
//and I can't find which flag enables that, anyways
|
||||
|
||||
SSPI->AcquireCredentialsHandleA(NULL, (char*)UNISP_NAME_A, SECPKG_CRED_OUTBOUND,
|
||||
NULL, &SchannelCred, NULL, NULL, &cred, NULL);
|
||||
}
|
||||
|
||||
class socketssl_impl : public socketssl {
|
||||
public:
|
||||
socket* sock;
|
||||
CtxtHandle ssl;
|
||||
SecPkgContext_StreamSizes bufsizes;
|
||||
|
||||
BYTE* recv_buf;
|
||||
size_t recv_buf_len;
|
||||
BYTE* ret_buf;
|
||||
size_t ret_buf_len;
|
||||
|
||||
bool in_handshake;
|
||||
|
||||
void fetch(bool block)
|
||||
{
|
||||
int bytes = sock->recv(recv_buf+recv_buf_len, 1024, block);
|
||||
if (bytes < 0)
|
||||
{
|
||||
delete sock;
|
||||
sock = NULL;
|
||||
}
|
||||
if (bytes > 0)
|
||||
{
|
||||
recv_buf_len += bytes;
|
||||
if (recv_buf_len > 1024)
|
||||
{
|
||||
recv_buf = realloc(recv_buf, recv_buf_len + 1024);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fetch() { fetch(true); }
|
||||
void fetchnb() { fetch(false); }
|
||||
|
||||
|
||||
void ret_realloc(int bytes)
|
||||
{
|
||||
if (bytes > 0)
|
||||
{
|
||||
ret_buf_len += bytes;
|
||||
if (ret_buf_len > 1024)
|
||||
{
|
||||
ret_buf = realloc(ret_buf, ret_buf_len + 1024);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BYTE* tmpptr()
|
||||
{
|
||||
return recv_buf + recv_buf_len;
|
||||
}
|
||||
|
||||
|
||||
void error()
|
||||
{
|
||||
SSPI->DeleteSecurityContext(&ssl);
|
||||
delete sock;
|
||||
sock = NULL;
|
||||
}
|
||||
|
||||
void handshake()
|
||||
{
|
||||
if (!in_handshake) return;
|
||||
|
||||
SecBuffer InBuffers[2] = { { recv_buf_len, SECBUFFER_TOKEN, recv_buf }, { 0, SECBUFFER_EMPTY, NULL } };
|
||||
SecBufferDesc InBufferDesc = { SECBUFFER_VERSION, 2, InBuffers };
|
||||
|
||||
SecBuffer OutBuffer = { 0, SECBUFFER_TOKEN, NULL };
|
||||
SecBufferDesc OutBufferDesc = { SECBUFFER_VERSION, 1, &OutBuffer };
|
||||
|
||||
DWORD ignore;
|
||||
SECURITY_STATUS scRet;
|
||||
scRet = SSPI->InitializeSecurityContextA(&cred, &ssl, NULL, SSPIFlags, 0, SECURITY_NATIVE_DREP,
|
||||
&InBufferDesc, 0, NULL, &OutBufferDesc, &ignore, NULL);
|
||||
|
||||
// according to the original program, extended errors are success
|
||||
// but they also hit the error handler below, so I guess it just sends an error to the server?
|
||||
// either way, ignore
|
||||
if (scRet == SEC_E_OK || scRet == SEC_I_CONTINUE_NEEDED)
|
||||
{
|
||||
if (OutBuffer.cbBuffer != 0 && OutBuffer.pvBuffer != NULL)
|
||||
{
|
||||
if (sock->send((BYTE*)OutBuffer.pvBuffer, OutBuffer.cbBuffer) < 0)
|
||||
{
|
||||
SSPI->FreeContextBuffer(OutBuffer.pvBuffer);
|
||||
error();
|
||||
return;
|
||||
}
|
||||
SSPI->FreeContextBuffer(OutBuffer.pvBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
if (scRet == SEC_E_INCOMPLETE_MESSAGE) return;
|
||||
|
||||
if (scRet == SEC_E_OK)
|
||||
{
|
||||
in_handshake = false;
|
||||
}
|
||||
|
||||
if (FAILED(scRet))
|
||||
{
|
||||
error();
|
||||
return;
|
||||
}
|
||||
|
||||
// SEC_I_INCOMPLETE_CREDENTIALS is possible and means server requested client authentication
|
||||
// we don't support that, just ignore it
|
||||
|
||||
if (InBuffers[1].BufferType == SECBUFFER_EXTRA)
|
||||
{
|
||||
memmove(recv_buf, recv_buf + (recv_buf_len - InBuffers[1].cbBuffer), InBuffers[1].cbBuffer);
|
||||
recv_buf_len = InBuffers[1].cbBuffer;
|
||||
}
|
||||
else recv_buf_len = 0;
|
||||
}
|
||||
|
||||
bool handshake_first(const char * domain)
|
||||
{
|
||||
SecBuffer OutBuffer = { 0, SECBUFFER_TOKEN, NULL };
|
||||
SecBufferDesc OutBufferDesc = { SECBUFFER_VERSION, 1, &OutBuffer };
|
||||
|
||||
DWORD ignore;
|
||||
if (SSPI->InitializeSecurityContextA(&cred, NULL, (char*)domain, SSPIFlags, 0, SECURITY_NATIVE_DREP,
|
||||
NULL, 0, &ssl, &OutBufferDesc, &ignore, NULL)
|
||||
!= SEC_I_CONTINUE_NEEDED)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (OutBuffer.cbBuffer != 0)
|
||||
{
|
||||
if (sock->send((BYTE*)OutBuffer.pvBuffer, OutBuffer.cbBuffer) < 0)
|
||||
{
|
||||
SSPI->FreeContextBuffer(OutBuffer.pvBuffer);
|
||||
error();
|
||||
return false;
|
||||
}
|
||||
SSPI->FreeContextBuffer(OutBuffer.pvBuffer); // Free output buffer.
|
||||
}
|
||||
|
||||
in_handshake = true;
|
||||
while (in_handshake) { fetch(); handshake(); }
|
||||
return true;
|
||||
}
|
||||
|
||||
bool init(socket* parent, const char * domain, bool permissive)
|
||||
{
|
||||
if (!parent) return false;
|
||||
|
||||
sock = parent;
|
||||
fd = parent->get_fd();
|
||||
recv_buf = malloc(2048);
|
||||
recv_buf_len = 0;
|
||||
ret_buf = malloc(2048);
|
||||
ret_buf_len = 0;
|
||||
|
||||
if (!handshake_first(domain)) return false;
|
||||
SSPI->QueryContextAttributes(&ssl, SECPKG_ATTR_STREAM_SIZES, &bufsizes);
|
||||
|
||||
return (sock);
|
||||
}
|
||||
|
||||
void process()
|
||||
{
|
||||
handshake();
|
||||
|
||||
bool again = true;
|
||||
|
||||
while (again)
|
||||
{
|
||||
again = false;
|
||||
|
||||
SecBuffer Buffers[4] = {
|
||||
{ recv_buf_len, SECBUFFER_DATA, recv_buf },
|
||||
{ 0, SECBUFFER_EMPTY, NULL },
|
||||
{ 0, SECBUFFER_EMPTY, NULL },
|
||||
{ 0, SECBUFFER_EMPTY, NULL },
|
||||
};
|
||||
SecBufferDesc Message = { SECBUFFER_VERSION, 4, Buffers };
|
||||
|
||||
SECURITY_STATUS scRet = SSPI->DecryptMessage(&ssl, &Message, 0, NULL);
|
||||
if (scRet == SEC_E_INCOMPLETE_MESSAGE) return;
|
||||
else if (scRet == SEC_I_RENEGOTIATE)
|
||||
{
|
||||
in_handshake = true;
|
||||
}
|
||||
else if (scRet != SEC_E_OK)
|
||||
{
|
||||
error();
|
||||
return;
|
||||
}
|
||||
|
||||
recv_buf_len = 0;
|
||||
|
||||
// Locate data and (optional) extra buffers.
|
||||
for (int i=0;i<4;i++)
|
||||
{
|
||||
if (Buffers[i].BufferType == SECBUFFER_DATA)
|
||||
{
|
||||
memcpy(ret_buf+ret_buf_len, Buffers[i].pvBuffer, Buffers[i].cbBuffer);
|
||||
ret_realloc(Buffers[i].cbBuffer);
|
||||
again = true;
|
||||
}
|
||||
if (Buffers[i].BufferType == SECBUFFER_EXTRA)
|
||||
{
|
||||
memmove(recv_buf, Buffers[i].pvBuffer, Buffers[i].cbBuffer);
|
||||
recv_buf_len = Buffers[i].cbBuffer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int recv(uint8_t* data, unsigned int len, bool block = false)
|
||||
{
|
||||
if (!sock) return -1;
|
||||
fetch(block);
|
||||
process();
|
||||
|
||||
if (!ret_buf_len) return 0;
|
||||
|
||||
unsigned ulen = len;
|
||||
int ret = (ulen < ret_buf_len ? ulen : ret_buf_len);
|
||||
memcpy(data, ret_buf, ret);
|
||||
memmove(ret_buf, ret_buf+ret, ret_buf_len-ret);
|
||||
ret_buf_len -= ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int sendp(const uint8_t* data, unsigned int len, bool block = true)
|
||||
{
|
||||
if (!sock) return -1;
|
||||
|
||||
fetchnb();
|
||||
process();
|
||||
|
||||
BYTE* sendbuf = tmpptr(); // let's reuse this
|
||||
|
||||
unsigned int maxmsglen = 0x1000 - bufsizes.cbHeader - bufsizes.cbTrailer;
|
||||
if (len > maxmsglen) len = maxmsglen;
|
||||
|
||||
memcpy(sendbuf+bufsizes.cbHeader, data, len);
|
||||
SecBuffer Buffers[4] = {
|
||||
{ bufsizes.cbHeader, SECBUFFER_STREAM_HEADER, sendbuf },
|
||||
{ len, SECBUFFER_DATA, sendbuf+bufsizes.cbHeader },
|
||||
{ bufsizes.cbTrailer, SECBUFFER_STREAM_TRAILER, sendbuf+bufsizes.cbHeader+len },
|
||||
{ 0, SECBUFFER_EMPTY, NULL },
|
||||
};
|
||||
SecBufferDesc Message = { SECBUFFER_VERSION, 4, Buffers };
|
||||
if (FAILED(SSPI->EncryptMessage(&ssl, 0, &Message, 0))) { error(); return -1; }
|
||||
|
||||
if (sock->send(sendbuf, Buffers[0].cbBuffer + Buffers[1].cbBuffer + Buffers[2].cbBuffer) < 0) error();
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
~socketssl_impl()
|
||||
{
|
||||
error();
|
||||
free(recv_buf);
|
||||
free(ret_buf);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
socketssl* socketssl::create(socket* parent, const char * domain, bool permissive)
|
||||
{
|
||||
initialize();
|
||||
socketssl_impl* ret = new socketssl_impl();
|
||||
if (!ret->init(parent, domain, permissive)) { delete ret; return NULL; }
|
||||
else return ret;
|
||||
}
|
||||
#endif
|
||||
5
arlib/socket/socket-test.cpp
Normal file
5
arlib/socket/socket-test.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
//TODO:
|
||||
//- fetch howsmyssl, ensure the only failure is the session cache
|
||||
//- ensure Subject Name is verified: fetch https://172.217.18.142/ (IP of google.com)
|
||||
//- ensure bad roots are rejected: fetch https://badfish.filippo.io/
|
||||
//- ensure bad certs are accepted with verification off
|
||||
260
arlib/socket/socket-tlse.cpp
Normal file
260
arlib/socket/socket-tlse.cpp
Normal file
@@ -0,0 +1,260 @@
|
||||
#include "socket.h"
|
||||
|
||||
#ifdef ARLIB_SSL_TLSE
|
||||
extern "C" {
|
||||
#include "tlse.h"
|
||||
}
|
||||
#include <sys/stat.h>
|
||||
#include <dirent.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
//TLSe flaws and limitations:
|
||||
//- can't share root certs between contexts (with possible exception of tls_accept, didn't check)
|
||||
//- lack of const on some functions
|
||||
//- have to load root certs myself
|
||||
//- had to implement Subject Alternative Name myself
|
||||
//- turns out tls_consume_stream(buf_len=0) throws an error - and no debug output
|
||||
//- tls_export_context return value seems be 'bytes expected' for inputlen=0 and inputlen>=expected,
|
||||
// but 'additional bytes expected' for inputlen=1
|
||||
//- lacks extern "C" on header
|
||||
//- lack of documentation
|
||||
|
||||
// separate context here to ensure they're not loaded multiple times, saves memory and time
|
||||
static TLSContext* rootcerts;
|
||||
|
||||
static void initialize()
|
||||
{
|
||||
if (rootcerts) return;
|
||||
|
||||
rootcerts = tls_create_context(false, TLS_V12);
|
||||
|
||||
#ifdef __unix__
|
||||
DIR* dir = opendir("/etc/ssl/certs/");
|
||||
uint8_t* cert = NULL;
|
||||
off_t cert_buf_len = 0;
|
||||
|
||||
if (dir)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
struct dirent* entry = readdir(dir);
|
||||
if (!entry) break;
|
||||
char name[256];
|
||||
snprintf(name, sizeof(name), "%s%s", "/etc/ssl/certs/", entry->d_name);
|
||||
|
||||
if (!strstr(name, "DST_Root")) continue;
|
||||
|
||||
struct stat s;
|
||||
if (stat(name, &s) == 0 && (s.st_mode & S_IFREG))
|
||||
{
|
||||
if (s.st_size > cert_buf_len)
|
||||
{
|
||||
free(cert);
|
||||
cert_buf_len = s.st_size;
|
||||
cert = (uint8_t*)malloc(cert_buf_len);
|
||||
}
|
||||
|
||||
int fd = open(name, O_RDONLY);
|
||||
if (fd >= 0)
|
||||
{
|
||||
off_t actualsize = read(fd, cert, s.st_size);
|
||||
tls_load_root_certificates(rootcerts, cert, actualsize);
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
}
|
||||
free(cert);
|
||||
#else
|
||||
#error unsupported
|
||||
#endif
|
||||
}
|
||||
|
||||
class socketssl_impl : public socketssl {
|
||||
public:
|
||||
socket* sock;
|
||||
TLSContext* ssl;
|
||||
|
||||
//same as tls_default_verify, except tls_certificate_chain_is_valid_root is given another context
|
||||
static int verify(TLSContext* context, TLSCertificate* * certificate_chain, int len) {
|
||||
int err;
|
||||
if (certificate_chain) {
|
||||
for (int i = 0; i < len; i++) {
|
||||
TLSCertificate* certificate = certificate_chain[i];
|
||||
// check validity date
|
||||
err = tls_certificate_is_valid(certificate);
|
||||
if (err)
|
||||
return err;
|
||||
// check certificate in certificate->bytes of length certificate->len
|
||||
// the certificate is in ASN.1 DER format
|
||||
}
|
||||
}
|
||||
// check if chain is valid
|
||||
err = tls_certificate_chain_is_valid(certificate_chain, len);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
const char * sni = tls_sni(context);
|
||||
if (len>0 && sni) {
|
||||
err = tls_certificate_valid_subject(certificate_chain[0], sni);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
// Perform certificate validation agains ROOT CA
|
||||
err = tls_certificate_chain_is_valid_root(rootcerts, certificate_chain, len);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
//return certificate_expired;
|
||||
//return certificate_revoked;
|
||||
//return certificate_unknown;
|
||||
return no_error;
|
||||
}
|
||||
|
||||
void process(bool block)
|
||||
{
|
||||
if (!sock) return;
|
||||
|
||||
unsigned int outlen = 0;
|
||||
const uint8_t * out = tls_get_write_buffer(ssl, &outlen);
|
||||
if (out && outlen)
|
||||
{
|
||||
if (sock->send(out, outlen) < 0) { error(); return; }
|
||||
tls_buffer_clear(ssl);
|
||||
}
|
||||
|
||||
uint8_t in[0x2000];
|
||||
int inlen = sock->recv(in, sizeof(in), block);
|
||||
if (inlen<0) { error(); return; }
|
||||
if (inlen>0) tls_consume_stream(ssl, in, inlen, verify);
|
||||
}
|
||||
|
||||
void error()
|
||||
{
|
||||
delete sock;
|
||||
sock = NULL;
|
||||
}
|
||||
|
||||
static socketssl_impl* create(socket* parent, const char * domain, bool permissive)
|
||||
{
|
||||
if (!parent) return NULL;
|
||||
|
||||
socketssl_impl* ret = new socketssl_impl();
|
||||
ret->sock = parent;
|
||||
ret->fd = parent->get_fd();
|
||||
|
||||
ret->ssl = tls_create_context(false, TLS_V12);
|
||||
|
||||
tls_make_exportable(ret->ssl, true);
|
||||
tls_sni_set(ret->ssl, domain);
|
||||
|
||||
tls_client_connect(ret->ssl);
|
||||
|
||||
while (!tls_established(ret->ssl))
|
||||
{
|
||||
ret->process(true);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int recv(uint8_t* data, unsigned int len, bool block = false)
|
||||
{
|
||||
process(block);
|
||||
|
||||
int ret = tls_read(ssl, data, len);
|
||||
if (ret==0 && !sock) return e_broken;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int sendp(const uint8_t* data, unsigned int len, bool block = true)
|
||||
{
|
||||
if (!sock) return -1;
|
||||
|
||||
int ret = tls_write(ssl, (uint8_t*)data, len);
|
||||
process(false);
|
||||
return ret;
|
||||
}
|
||||
|
||||
~socketssl_impl()
|
||||
{
|
||||
if (ssl && sock)
|
||||
{
|
||||
tls_close_notify(ssl);
|
||||
process(false);
|
||||
}
|
||||
if (ssl) tls_destroy_context(ssl);
|
||||
if (sock) delete sock;
|
||||
}
|
||||
|
||||
void q()
|
||||
{
|
||||
uint8_t data[4096];
|
||||
int len = tls_export_context(ssl, NULL, 0, false);
|
||||
int len2 = tls_export_context(ssl, data, len, false);
|
||||
printf("len=%i len2=%i\n", len, len2);
|
||||
//tls_destroy_context(ssl);
|
||||
|
||||
TLSContext* ssl2 = tls_import_context(data, len);
|
||||
|
||||
uint8_t* p1 = (uint8_t*)ssl;
|
||||
uint8_t* p2 = (uint8_t*)ssl2;
|
||||
for (int i=0;i<140304;i++)
|
||||
{
|
||||
//if (p1[i] != p2[i]) printf("%i: g=%.2X b=%.2X\n", i, p1[i], p2[i]);
|
||||
}
|
||||
|
||||
//ssl = ssl2;
|
||||
}
|
||||
|
||||
|
||||
size_t serialize_size()
|
||||
{
|
||||
return tls_export_context(ssl, NULL, 0, false);
|
||||
}
|
||||
|
||||
int serialize(uint8_t* data, size_t len)
|
||||
{
|
||||
process(true);
|
||||
|
||||
tls_export_context(ssl, data, len, false);
|
||||
|
||||
tls_destroy_context(this->ssl);
|
||||
this->ssl = NULL;
|
||||
|
||||
int ret = decompose(this->sock);
|
||||
this->sock = NULL;
|
||||
|
||||
delete this;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static socketssl_impl* unserialize(int fd, const uint8_t* data, size_t len)
|
||||
{
|
||||
socketssl_impl* ret = new socketssl_impl();
|
||||
ret->sock = socket::create_from_fd(fd);
|
||||
ret->fd = fd;
|
||||
ret->ssl = tls_import_context((uint8_t*)data, len);
|
||||
if (!ret->ssl) { delete ret; return NULL; }
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
socketssl* socketssl::create(socket* parent, const char * domain, bool permissive)
|
||||
{
|
||||
initialize();
|
||||
return socketssl_impl::create(parent, domain, permissive);
|
||||
}
|
||||
|
||||
socketssl* socketssl::unserialize(int fd, const uint8_t* data, size_t len)
|
||||
{
|
||||
initialize();
|
||||
return socketssl_impl::unserialize(fd, data, len);
|
||||
}
|
||||
#endif
|
||||
241
arlib/socket/socket-wolfssl.cpp
Normal file
241
arlib/socket/socket-wolfssl.cpp
Normal file
@@ -0,0 +1,241 @@
|
||||
#include "socket.h"
|
||||
|
||||
#ifdef ARLIB_SSL_WOLFSSL
|
||||
//#define HAVE_SNI
|
||||
#define HAVE_SUPPORTED_CURVES
|
||||
#include <wolfssl/ssl.h>
|
||||
#ifdef __unix__
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
|
||||
#error "this thing is broken. try again once wolfSSL > 3.9 is released and see if that fixes the alert 40 handshake failed errors"
|
||||
|
||||
static WOLFSSL_CTX* ctx;
|
||||
|
||||
class socketssl_impl : public socketssl {
|
||||
public:
|
||||
socket* sock;
|
||||
WOLFSSL* ssl;
|
||||
bool nonblock;
|
||||
|
||||
socketssl_impl(socket* parent, const char * domain, bool permissive)
|
||||
{
|
||||
sock = parent;
|
||||
fd = get_fd(parent);
|
||||
//ssl = wolfSSL_new(ctx);
|
||||
nonblock = 0;
|
||||
|
||||
wolfSSL_Init();
|
||||
wolfSSL_Debugging_ON();
|
||||
ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method());
|
||||
wolfSSL_SetIORecv(ctx, socketssl_impl::recv_raw);
|
||||
wolfSSL_SetIOSend(ctx, socketssl_impl::send_raw);
|
||||
|
||||
wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0);
|
||||
|
||||
#define err_sys puts
|
||||
ssl = wolfSSL_new(ctx);
|
||||
|
||||
wolfSSL_SetIOReadCtx(ssl, this);
|
||||
wolfSSL_SetIOWriteCtx(ssl, this);
|
||||
|
||||
if (ssl == NULL)
|
||||
err_sys("unable to get SSL object");
|
||||
|
||||
if (wolfSSL_UseSupportedCurve(ssl, WOLFSSL_ECC_SECP256R1)
|
||||
!= SSL_SUCCESS) {
|
||||
err_sys("unable to set curve secp256r1");
|
||||
}
|
||||
if (wolfSSL_UseSupportedCurve(ssl, WOLFSSL_ECC_SECP384R1)
|
||||
!= SSL_SUCCESS) {
|
||||
err_sys("unable to set curve secp384r1");
|
||||
}
|
||||
if (wolfSSL_UseSupportedCurve(ssl, WOLFSSL_ECC_SECP521R1)
|
||||
!= SSL_SUCCESS) {
|
||||
err_sys("unable to set curve secp521r1");
|
||||
}
|
||||
if (wolfSSL_UseSupportedCurve(ssl, WOLFSSL_ECC_SECP224R1)
|
||||
!= SSL_SUCCESS) {
|
||||
err_sys("unable to set curve secp224r1");
|
||||
}
|
||||
if (wolfSSL_UseSupportedCurve(ssl, WOLFSSL_ECC_SECP192R1)
|
||||
!= SSL_SUCCESS) {
|
||||
err_sys("unable to set curve secp192r1");
|
||||
}
|
||||
if (wolfSSL_UseSupportedCurve(ssl, WOLFSSL_ECC_SECP160R1)
|
||||
!= SSL_SUCCESS) {
|
||||
err_sys("unable to set curve secp160r1");
|
||||
}
|
||||
|
||||
//printf("fd=%i ret=%i ok=%i f=%i\n", fd,
|
||||
//wolfSSL_set_fd(ssl, fd),
|
||||
//SSL_SUCCESS, SSL_FAILURE);
|
||||
|
||||
puts("AAAAAAA");
|
||||
if (wolfSSL_connect(ssl) != SSL_SUCCESS) {puts("NOOO");}
|
||||
|
||||
//wolfSSL_check_domain_name(ssl, domain);
|
||||
|
||||
|
||||
//#define err_sys puts
|
||||
// if (wolfSSL_UseSupportedCurve(ssl, WOLFSSL_ECC_SECP256R1)
|
||||
// != SSL_SUCCESS) {
|
||||
// err_sys("unable to set curve secp256r1");
|
||||
// }
|
||||
// if (wolfSSL_UseSupportedCurve(ssl, WOLFSSL_ECC_SECP384R1)
|
||||
// != SSL_SUCCESS) {
|
||||
// err_sys("unable to set curve secp384r1");
|
||||
// }
|
||||
// if (wolfSSL_UseSupportedCurve(ssl, WOLFSSL_ECC_SECP521R1)
|
||||
// != SSL_SUCCESS) {
|
||||
// err_sys("unable to set curve secp521r1");
|
||||
// }
|
||||
// if (wolfSSL_UseSupportedCurve(ssl, WOLFSSL_ECC_SECP224R1)
|
||||
// != SSL_SUCCESS) {
|
||||
// err_sys("unable to set curve secp224r1");
|
||||
// }
|
||||
// if (wolfSSL_UseSupportedCurve(ssl, WOLFSSL_ECC_SECP192R1)
|
||||
// != SSL_SUCCESS) {
|
||||
// err_sys("unable to set curve secp192r1");
|
||||
// }
|
||||
// if (wolfSSL_UseSupportedCurve(ssl, WOLFSSL_ECC_SECP160R1)
|
||||
// != SSL_SUCCESS) {
|
||||
// err_sys("unable to set curve secp160r1");
|
||||
// }
|
||||
//
|
||||
// wolfSSL_set_fd(ssl, fd);
|
||||
// puts("cactus");
|
||||
// if (wolfSSL_connect(ssl) != SSL_SUCCESS) {
|
||||
// /* see note at top of README */
|
||||
// int err = wolfSSL_get_error(ssl, 0);
|
||||
// char buffer[80];
|
||||
// printf("err = %d, %s\n", err,
|
||||
// wolfSSL_ERR_error_string(err, buffer));
|
||||
// err_sys("SSL_connect failed");
|
||||
// /* if you're getting an error here */
|
||||
// }
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/*private*/ static int recv_raw(WOLFSSL* ssl, char* buf, int sz, void* ctx)
|
||||
{
|
||||
socketssl_impl* this_ = (socketssl_impl*)ctx;
|
||||
int ret = this_->sock->recv((uint8_t*)buf, sz);
|
||||
printf("SSLDATRAW_R=%i\n",ret);
|
||||
for(int i=0;i<ret;i++)printf("%.2X ",(uint8_t)buf[i]);
|
||||
puts("");
|
||||
if (ret==0) return WOLFSSL_CBIO_ERR_WANT_READ;
|
||||
if (ret<0) return WOLFSSL_CBIO_ERR_GENERAL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*private*/ static int send_raw(WOLFSSL* ssl, char* buf, int sz, void* ctx)
|
||||
{
|
||||
socketssl_impl* this_ = (socketssl_impl*)ctx;
|
||||
int ret;
|
||||
if (this_->nonblock) ret = this_->sock->send0((uint8_t*)buf, sz);
|
||||
else ret = this_->sock->send1((uint8_t*)buf, sz);
|
||||
printf("SSLDATRAW_S=%i\n",ret);
|
||||
for(int i=0;i<ret;i++)printf("%.2X ",(uint8_t)buf[i]);
|
||||
puts("");
|
||||
if (ret==0) return WOLFSSL_CBIO_ERR_WANT_WRITE;
|
||||
if (ret<0) return WOLFSSL_CBIO_ERR_GENERAL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*private*/ int fixret(int ret)
|
||||
{
|
||||
printf("SSLDAT=%i\n",ret);
|
||||
if (ret > 0) return ret;
|
||||
|
||||
int err = wolfSSL_get_error(ssl, ret);
|
||||
if (err==SSL_ERROR_WANT_READ || err==SSL_ERROR_WANT_WRITE) return 0;
|
||||
printf("SSLERR=%i\n",err);
|
||||
return e_broken;
|
||||
}
|
||||
|
||||
int recv(uint8_t* data, int len)
|
||||
{
|
||||
nonblock = false;
|
||||
return fixret(wolfSSL_read(ssl, data, len));
|
||||
}
|
||||
|
||||
int send0(const uint8_t* data, int len)
|
||||
{
|
||||
nonblock = true;
|
||||
return fixret(wolfSSL_write(ssl, data, len));
|
||||
}
|
||||
|
||||
int send1(const uint8_t* data, int len)
|
||||
{
|
||||
nonblock = false;
|
||||
return fixret(wolfSSL_write(ssl, data, len));
|
||||
}
|
||||
|
||||
~socketssl_impl()
|
||||
{
|
||||
wolfSSL_free(ssl);
|
||||
delete sock;
|
||||
}
|
||||
};
|
||||
|
||||
static void initialize()
|
||||
{
|
||||
static bool initialized = false;
|
||||
if (initialized) return;
|
||||
initialized = true;
|
||||
|
||||
|
||||
|
||||
|
||||
//wolfSSL_Init();
|
||||
//
|
||||
//ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method());
|
||||
//if (!ctx) return;
|
||||
//wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0);
|
||||
|
||||
//wolfSSL_SetIORecv(ctx, socketssl_impl::recv_raw);
|
||||
//wolfSSL_SetIOSend(ctx, socketssl_impl::send_raw);
|
||||
|
||||
#ifdef __unix__
|
||||
//mostly copypasta from wolfSSL_CTX_load_verify_locations, minus the abort-on-first-error thingy
|
||||
//there's some random weirdo files in my /etc/ssl/certs/, possibly duplicates?
|
||||
//DIR* dir = opendir("/etc/ssl/certs/");
|
||||
//if (dir)
|
||||
//{
|
||||
//while (true)
|
||||
//{
|
||||
//struct dirent* entry = readdir(dir);
|
||||
//if (!entry) break;
|
||||
//char name[256];
|
||||
//snprintf(name, sizeof(name), "%s%s", "/etc/ssl/certs/", entry->d_name);
|
||||
//
|
||||
//struct stat s;
|
||||
//if (stat(name, &s) == 0 && (s.st_mode & S_IFREG))
|
||||
//{
|
||||
//printf("cert=%s\n",name);
|
||||
//wolfSSL_CTX_load_verify_locations(ctx, name, NULL);
|
||||
//}
|
||||
//}
|
||||
//closedir(dir);
|
||||
//}
|
||||
#else
|
||||
#error unsupported
|
||||
#endif
|
||||
//wolfSSL_Debugging_ON();
|
||||
}
|
||||
|
||||
socketssl* socketssl::create(socket* parent, const char * domain, bool permissive)
|
||||
{
|
||||
initialize();
|
||||
//if (!ctx) return NULL;
|
||||
|
||||
return new socketssl_impl(parent, domain, permissive);
|
||||
}
|
||||
#endif
|
||||
160
arlib/socket/socket.cpp
Normal file
160
arlib/socket/socket.cpp
Normal file
@@ -0,0 +1,160 @@
|
||||
#include "socket.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#undef socket
|
||||
#undef bind
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#define MSG_NOSIGNAL 0
|
||||
#define MSG_DONTWAIT 0
|
||||
#define close closesocket
|
||||
#define usleep(n) Sleep(n/1000)
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment(lib, "ws2_32.lib")
|
||||
#endif
|
||||
#else
|
||||
#include <netdb.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
static int setsockopt(int socket, int level, int option_name, int option_value)
|
||||
{
|
||||
return setsockopt(socket, level, option_name, &option_value, sizeof(option_value));
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
static void initialize()
|
||||
{
|
||||
#ifdef _WIN32 // lol
|
||||
static bool initialized = false;
|
||||
if (initialized) return;
|
||||
initialized = true;
|
||||
|
||||
WSADATA wsaData;
|
||||
WSAStartup(MAKEWORD(2, 2), &wsaData);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int connect(const char * domain, int port)
|
||||
{
|
||||
initialize();
|
||||
|
||||
char portstr[16];
|
||||
sprintf(portstr, "%i", port);
|
||||
|
||||
addrinfo hints;
|
||||
memset(&hints, 0, sizeof(addrinfo));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_flags = 0;
|
||||
|
||||
addrinfo * addr = NULL;
|
||||
getaddrinfo(domain, portstr, &hints, &addr);
|
||||
if (!addr) return -1;
|
||||
|
||||
int fd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
|
||||
#ifndef _WIN32
|
||||
//because 30 second pauses are unequivocally detestable
|
||||
timeval timeout;
|
||||
timeout.tv_sec = 4;
|
||||
timeout.tv_usec = 0;
|
||||
setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof(timeout));
|
||||
#endif
|
||||
if (connect(fd, addr->ai_addr, addr->ai_addrlen) != 0)
|
||||
{
|
||||
freeaddrinfo(addr);
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
#ifndef _WIN32
|
||||
setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, 1); // enable
|
||||
setsockopt(fd, SOL_TCP, TCP_KEEPCNT, 3); // ping count before the kernel gives up
|
||||
setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, 30); // seconds idle until it starts pinging
|
||||
setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, 10); // seconds per ping once the pings start
|
||||
#else
|
||||
u_long yes = 1;
|
||||
ioctlsocket(fd, FIONBIO, &yes);
|
||||
|
||||
struct tcp_keepalive keepalive = {
|
||||
1, // SO_KEEPALIVE
|
||||
30*1000, // TCP_KEEPIDLE in milliseconds
|
||||
3*1000, // TCP_KEEPINTVL
|
||||
//On Windows Vista and later, the number of keep-alive probes (data retransmissions) is set to 10 and cannot be changed.
|
||||
//https://msdn.microsoft.com/en-us/library/windows/desktop/dd877220(v=vs.85).aspx
|
||||
//so no TCP_KEEPCNT; I'll reduce INTVL instead. And a polite server will RST anyways.
|
||||
};
|
||||
u_long ignore;
|
||||
WSAIoctl(fd, SIO_KEEPALIVE_VALS, &keepalive, sizeof(keepalive), NULL, 0, &ignore, NULL, NULL);
|
||||
#endif
|
||||
|
||||
freeaddrinfo(addr);
|
||||
return fd;
|
||||
}
|
||||
|
||||
#define socket socket_t
|
||||
class socket_impl : public socket {
|
||||
public:
|
||||
socket_impl(int fd) { this->fd = fd; }
|
||||
|
||||
/*private*/ int fixret(int ret)
|
||||
{
|
||||
//printf("r=%i e=%i wb=%i\n", ret, WSAGetLastError(), WSAEWOULDBLOCK);
|
||||
if (ret > 0) return ret;
|
||||
if (ret == 0) return e_closed;
|
||||
#ifdef __unix__
|
||||
if (ret < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) return 0;
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
if (ret < 0 && WSAGetLastError() == WSAEWOULDBLOCK) return 0;
|
||||
#endif
|
||||
return e_broken;
|
||||
}
|
||||
|
||||
int recv(uint8_t* data, unsigned int len, bool block = false)
|
||||
{
|
||||
return fixret(::recv(fd, (char*)data, len, MSG_NOSIGNAL | (block ? 0 : MSG_DONTWAIT)));
|
||||
}
|
||||
|
||||
int sendp(const uint8_t* data, unsigned int len, bool block = true)
|
||||
{
|
||||
//printf("snd=%i\n",len);
|
||||
return fixret(::send(fd, (char*)data, len, MSG_NOSIGNAL | (block ? 0 : MSG_DONTWAIT)));
|
||||
}
|
||||
|
||||
~socket_impl()
|
||||
{
|
||||
close(fd);
|
||||
}
|
||||
};
|
||||
|
||||
static socket* socket_wrap(int fd)
|
||||
{
|
||||
if (fd<0) return NULL;
|
||||
return new socket_impl(fd);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
socket* socket::create_from_fd(int fd)
|
||||
{
|
||||
return socket_wrap(fd);
|
||||
}
|
||||
|
||||
socket* socket::create(const char * domain, int port)
|
||||
{
|
||||
return socket_wrap(connect(domain, port));
|
||||
}
|
||||
|
||||
//static socket* create_async(const char * domain, int port);
|
||||
//static socket* create_udp(const char * domain, int port);
|
||||
|
||||
//int socket::select(socket* * socks, int nsocks, int timeout_ms)
|
||||
//{
|
||||
// return -1;
|
||||
//}
|
||||
99
arlib/socket/socket.h
Normal file
99
arlib/socket/socket.h
Normal file
@@ -0,0 +1,99 @@
|
||||
#include "../global.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#define socket socket_t
|
||||
class socket : nocopy {
|
||||
protected:
|
||||
socket(){}
|
||||
int fd; // Used by select().
|
||||
|
||||
//deallocates the socket, returning its fd, while letting the fd remain valid
|
||||
static int decompose(socket* sock) { int ret = sock->fd; sock->fd=-1; delete sock; return ret; }
|
||||
|
||||
public:
|
||||
//Returns NULL on connection failure.
|
||||
static socket* create(const char * domain, int port);
|
||||
//Always succeeds. If the server can't be contacted, returns failure on first write or read.
|
||||
static socket* create_async(const char * domain, int port);
|
||||
static socket* create_udp(const char * domain, int port);
|
||||
|
||||
enum {
|
||||
e_lazy_dev = -1, // Whoever implemented this socket layer was lazy and just returned -1. Treat it as e_broken or an unknown error.
|
||||
e_closed = -2, // Remote host chose to gracefully close the connection.
|
||||
e_broken = -3, // Connection was forcibly torn down.
|
||||
e_udp_too_big = -4, // Attempted to process an unacceptably large UDP packet.
|
||||
e_ssl_failure = -5, // Certificate validation failed, no algorithms in common, or other SSL error.
|
||||
};
|
||||
|
||||
//Negative means error, see above.
|
||||
//Positive is number of bytes handled.
|
||||
//WARNING: Unlike most socket layers, zero does not mean graceful close!
|
||||
// It means success, zero bytes processed, and is a valid byte count. Socket closed is in the error list above.
|
||||
//The first two functions will process at least one byte, or if block is false, at least zero. send() sends all bytes before returning.
|
||||
//block is ignored on Windows (always false), due to lack of MSG_NOWAIT and I don't want to do another syscall every time.
|
||||
//For UDP sockets, partial reads or writes aren't possible; you always get one or zero packets.
|
||||
virtual int recv(uint8_t* data, unsigned int len, bool block = true) = 0;
|
||||
virtual int sendp(const uint8_t* data, unsigned int len, bool block = true) = 0;
|
||||
int send(const uint8_t* data, unsigned int len)
|
||||
{
|
||||
unsigned int sent = 0;
|
||||
while (sent < len)
|
||||
{
|
||||
int here = sendp(data+sent, len-sent);
|
||||
if (here<0) return here;
|
||||
sent += here;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
//Convenience functions for handling textual data.
|
||||
int recv(char* data, unsigned int len, bool block = false)
|
||||
{
|
||||
int ret = recv((uint8_t*)data, len-1, block);
|
||||
if (ret >= 0) data[ret]='\0';
|
||||
else data[0]='\0';
|
||||
return ret;
|
||||
}
|
||||
int sendp(const char * data, bool block = true) { return sendp((uint8_t*)data, strlen(data), block); }
|
||||
int send (const char * data) { return send((uint8_t*)data, strlen(data)); }
|
||||
|
||||
//Returns an index to the sockets array, or negative if timeout expires.
|
||||
//Negative timeouts mean wait forever.
|
||||
//It's possible that an active socket returns zero bytes.
|
||||
//However, this is guaranteed to happen rarely enough that repeatedly select()ing will leave the CPU mostly idle.
|
||||
//(It may be caused by packets with wrong checksum, SSL renegotiation, or whatever.)
|
||||
static int select(socket* * socks, unsigned int nsocks, int timeout_ms = -1);
|
||||
|
||||
virtual ~socket() {}
|
||||
|
||||
//Can be used to keep a socket alive across exec(). Don't use for an SSL socket.
|
||||
static socket* create_from_fd(int fd);
|
||||
int get_fd() { return fd; }
|
||||
};
|
||||
|
||||
class socketssl : public socket {
|
||||
protected:
|
||||
socketssl(){}
|
||||
public:
|
||||
//If 'permissive' is true, expired and self-signed server certificates will be accepted.
|
||||
//Other invalid certs, such as ones for a different domain, may or may not be accepted.
|
||||
static socketssl* create(const char * domain, int port, bool permissive=false)
|
||||
{
|
||||
return socketssl::create(socket::create(domain, port), domain, permissive);
|
||||
}
|
||||
//On entry, this takes ownership of the socket. Even if connection fails, the socket may not be used anymore.
|
||||
//The socket must be a normal TCP socket. UDP and nested SSL is not supported.
|
||||
static socketssl* create(socket* parent, const char * domain, bool permissive=false);
|
||||
|
||||
|
||||
virtual void q(){}
|
||||
|
||||
//Can be used to keep a socket alive across exec().
|
||||
//If successful, serialize() returns the the file descriptor needed to unserialize, and the socket is deleted.
|
||||
//If failure, negative return and nothing happens.
|
||||
virtual size_t serialize_size() { return 0; }
|
||||
virtual int serialize(uint8_t* data, size_t len) { return -1; }
|
||||
static socketssl* unserialize(int fd, const uint8_t* data, size_t len);
|
||||
};
|
||||
109
arlib/socket/test.c
Normal file
109
arlib/socket/test.c
Normal file
@@ -0,0 +1,109 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#define socklen_t int
|
||||
#define sleep(x) Sleep(x*1000)
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
#include "tlse.c"
|
||||
|
||||
void error(char *msg) {
|
||||
perror(msg);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int send_pending(int client_sock, struct TLSContext *context) {
|
||||
unsigned int out_buffer_len = 0;
|
||||
const unsigned char *out_buffer = tls_get_write_buffer(context, &out_buffer_len);
|
||||
unsigned int out_buffer_index = 0;
|
||||
int send_res = 0;
|
||||
while ((out_buffer) && (out_buffer_len > 0)) {
|
||||
int res = send(client_sock, (char *)&out_buffer[out_buffer_index], out_buffer_len, 0);
|
||||
if (res <= 0) {
|
||||
send_res = res;
|
||||
break;
|
||||
}
|
||||
out_buffer_len -= res;
|
||||
out_buffer_index += res;
|
||||
}
|
||||
tls_buffer_clear(context);
|
||||
return send_res;
|
||||
}
|
||||
|
||||
int validate_certificate(struct TLSContext *context, struct TLSCertificate **certificate_chain, int len) {
|
||||
int i;
|
||||
if (certificate_chain) {
|
||||
for (i = 0; i < len; i++) {
|
||||
struct TLSCertificate *certificate = certificate_chain[i];
|
||||
// check certificate ...
|
||||
}
|
||||
}
|
||||
//return certificate_expired;
|
||||
//return certificate_revoked;
|
||||
//return certificate_unknown;
|
||||
return no_error;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int sockfd, portno, n;
|
||||
//tls_print_certificate("testcert/server.certificate");
|
||||
//tls_print_certificate("000.certificate");
|
||||
//exit(0);
|
||||
struct sockaddr_in serv_addr;
|
||||
struct hostent *server;
|
||||
|
||||
char buffer[256];
|
||||
char *ref_argv[] = {"", "google.com", "443"};
|
||||
if (argc < 3) {
|
||||
argv = ref_argv;
|
||||
//fprintf(stderr,"usage %s hostname port\n", argv[0]);
|
||||
//exit(0);
|
||||
}
|
||||
#ifdef _WIN32
|
||||
WSADATA wsaData;
|
||||
WSAStartup(MAKEWORD(2, 2), &wsaData);
|
||||
#else
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
#endif
|
||||
portno = atoi(argv[2]);
|
||||
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (sockfd < 0)
|
||||
error("ERROR opening socket");
|
||||
server = gethostbyname(argv[1]);
|
||||
if (server == NULL) {
|
||||
fprintf(stderr,"ERROR, no such host\n");
|
||||
exit(0);
|
||||
}
|
||||
memset((char *) &serv_addr, 0, sizeof(serv_addr));
|
||||
serv_addr.sin_family = AF_INET;
|
||||
memcpy((char *)&serv_addr.sin_addr.s_addr, (char *)server->h_addr, server->h_length);
|
||||
serv_addr.sin_port = htons(portno);
|
||||
if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
|
||||
error("ERROR connecting");
|
||||
|
||||
struct TLSContext *context = tls_create_context(0, TLS_V12);
|
||||
tls_client_connect(context);
|
||||
send_pending(sockfd, context);
|
||||
unsigned char client_message[0xFFFF];
|
||||
int read_size;
|
||||
while ((read_size = recv(sockfd, client_message, sizeof(client_message) , 0)) > 0) {
|
||||
tls_consume_stream(context, client_message, read_size, validate_certificate);
|
||||
send_pending(sockfd, context);
|
||||
if (tls_established(context)) {
|
||||
const char * out = "GET / HTTP/1.1\nHost: example.com\nConnection: close\n\n";
|
||||
tls_write(context, out, strlen(out));
|
||||
send_pending(sockfd, context);
|
||||
|
||||
unsigned char read_buffer[0xFFFF];
|
||||
int read_size = tls_read(context, read_buffer, 0xFFFF - 1);
|
||||
if (read_size > 0)
|
||||
fwrite(read_buffer, read_size, 1, stdout);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
7974
arlib/socket/tlse.c
Normal file
7974
arlib/socket/tlse.c
Normal file
File diff suppressed because it is too large
Load Diff
276
arlib/socket/tlse.h
Normal file
276
arlib/socket/tlse.h
Normal file
@@ -0,0 +1,276 @@
|
||||
// from https://github.com/eduardsui/tlse
|
||||
#ifndef TLSE_H
|
||||
#define TLSE_H
|
||||
|
||||
// #define DEBUG
|
||||
|
||||
// define TLS_LEGACY_SUPPORT to support TLS 1.1/1.0 (legacy)
|
||||
// legacy support it will use an additional 272 bytes / context
|
||||
#define TLS_LEGACY_SUPPORT
|
||||
// SSL_* style blocking APIs
|
||||
#define SSL_COMPATIBLE_INTERFACE
|
||||
// support forward secrecy (Diffie-Hellman ephemeral)
|
||||
#define TLS_FORWARD_SECRECY
|
||||
// support client-side ECDHE
|
||||
#define TLS_CLIENT_ECDHE
|
||||
// suport ecdsa
|
||||
#define TLS_ECDSA_SUPPORTED
|
||||
// TLS renegotiation is disabled by default (secured or not)
|
||||
// do not uncomment next line!
|
||||
// #define TLS_ACCEPT_SECURE_RENEGOTIATION
|
||||
|
||||
#define TLS_V10 0x0301
|
||||
#define TLS_V11 0x0302
|
||||
#define TLS_V12 0x0303
|
||||
#define DTLS_V10 0xFEFF
|
||||
#define DTLS_V12 0xFEFD
|
||||
|
||||
#define TLS_NEED_MORE_DATA 0
|
||||
#define TLS_GENERIC_ERROR -1
|
||||
#define TLS_BROKEN_PACKET -2
|
||||
#define TLS_NOT_UNDERSTOOD -3
|
||||
#define TLS_NOT_SAFE -4
|
||||
#define TLS_NO_COMMON_CIPHER -5
|
||||
#define TLS_UNEXPECTED_MESSAGE -6
|
||||
#define TLS_CLOSE_CONNECTION -7
|
||||
#define TLS_COMPRESSION_NOT_SUPPORTED -8
|
||||
#define TLS_NO_MEMORY -9
|
||||
#define TLS_NOT_VERIFIED -10
|
||||
#define TLS_INTEGRITY_FAILED -11
|
||||
#define TLS_ERROR_ALERT -12
|
||||
#define TLS_BROKEN_CONNECTION -13
|
||||
#define TLS_BAD_CERTIFICATE -14
|
||||
#define TLS_UNSUPPORTED_CERTIFICATE -15
|
||||
#define TLS_NO_RENEGOTIATION -16
|
||||
#define TLS_FEATURE_NOT_SUPPORTED -17
|
||||
|
||||
#define TLS_RSA_WITH_AES_128_CBC_SHA 0x002F
|
||||
#define TLS_RSA_WITH_AES_256_CBC_SHA 0x0035
|
||||
#define TLS_RSA_WITH_AES_128_CBC_SHA256 0x003C
|
||||
#define TLS_RSA_WITH_AES_256_CBC_SHA256 0x003D
|
||||
#define TLS_RSA_WITH_AES_128_GCM_SHA256 0x009C
|
||||
#define TLS_RSA_WITH_AES_256_GCM_SHA384 0x009D
|
||||
|
||||
// forward secrecy
|
||||
#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x0033
|
||||
#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x0039
|
||||
#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 0x0067
|
||||
#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 0x006B
|
||||
#define TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 0x009E
|
||||
#define TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 0x009F
|
||||
|
||||
#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC013
|
||||
#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC014
|
||||
#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xC027
|
||||
#define TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC02F
|
||||
#define TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xC030
|
||||
|
||||
#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0xC009
|
||||
#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0xC00A
|
||||
#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023
|
||||
#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 0xC024
|
||||
#define TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B
|
||||
#define TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0xC02C
|
||||
|
||||
#define TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA8
|
||||
#define TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA9
|
||||
#define TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCAA
|
||||
|
||||
#define TLS_FALLBACK_SCSV 0x5600
|
||||
|
||||
#define TLS_UNSUPPORTED_ALGORITHM 0x00
|
||||
#define TLS_RSA_SIGN_RSA 0x01
|
||||
#define TLS_RSA_SIGN_MD5 0x04
|
||||
#define TLS_RSA_SIGN_SHA1 0x05
|
||||
#define TLS_RSA_SIGN_SHA256 0x0B
|
||||
#define TLS_RSA_SIGN_SHA384 0x0C
|
||||
#define TLS_RSA_SIGN_SHA512 0x0D
|
||||
|
||||
#define TLS_EC_PUBLIC_KEY 0x11
|
||||
#define TLS_EC_prime192v1 0x12
|
||||
#define TLS_EC_prime192v2 0x13
|
||||
#define TLS_EC_prime192v3 0x14
|
||||
#define TLS_EC_prime239v1 0x15
|
||||
#define TLS_EC_prime239v2 0x16
|
||||
#define TLS_EC_prime239v3 0x17
|
||||
#define TLS_EC_prime256v1 0x18
|
||||
#define TLS_EC_secp224r1 21
|
||||
#define TLS_EC_secp256r1 23
|
||||
#define TLS_EC_secp384r1 24
|
||||
#define TLS_EC_secp521r1 25
|
||||
|
||||
#define TLS_ALERT_WARNING 0x01
|
||||
#define TLS_ALERT_CRITICAL 0x02
|
||||
|
||||
typedef enum {
|
||||
close_notify = 0,
|
||||
unexpected_message = 10,
|
||||
bad_record_mac = 20,
|
||||
decryption_failed_RESERVED = 21,
|
||||
record_overflow = 22,
|
||||
decompression_failure = 30,
|
||||
handshake_failure = 40,
|
||||
no_certificate_RESERVED = 41,
|
||||
bad_certificate = 42,
|
||||
unsupported_certificate = 43,
|
||||
certificate_revoked = 44,
|
||||
certificate_expired = 45,
|
||||
certificate_unknown = 46,
|
||||
illegal_parameter = 47,
|
||||
unknown_ca = 48,
|
||||
access_denied = 49,
|
||||
decode_error = 50,
|
||||
decrypt_error = 51,
|
||||
export_restriction_RESERVED = 60,
|
||||
protocol_version = 70,
|
||||
insufficient_security = 71,
|
||||
internal_error = 80,
|
||||
inappropriate_fallback = 86,
|
||||
user_canceled = 90,
|
||||
no_renegotiation = 100,
|
||||
unsupported_extension = 110,
|
||||
no_error = 255
|
||||
} TLSAlertDescription;
|
||||
|
||||
// forward declarations
|
||||
struct TLSPacket;
|
||||
struct TLSCertificate;
|
||||
struct TLSContext;
|
||||
struct ECCCurveParameters;
|
||||
typedef struct TLSContext TLS;
|
||||
typedef struct TLSCertificate Certificate;
|
||||
|
||||
typedef int (*tls_validation_function)(struct TLSContext *context, struct TLSCertificate **certificate_chain, int len);
|
||||
|
||||
unsigned char *tls_pem_decode(const unsigned char *data_in, unsigned int input_length, int cert_index, unsigned int *output_len);
|
||||
struct TLSCertificate *tls_create_certificate();
|
||||
int tls_certificate_valid_subject(struct TLSCertificate *cert, const char *subject);
|
||||
int tls_certificate_valid_subject_name(const unsigned char *cert_subject, const char *subject);
|
||||
int tls_certificate_is_valid(struct TLSCertificate *cert);
|
||||
void tls_certificate_set_copy(unsigned char **member, const unsigned char *val, int len);
|
||||
void tls_certificate_set_copy_date(unsigned char **member, const unsigned char *val, int len);
|
||||
void tls_certificate_set_key(struct TLSCertificate *cert, const unsigned char *val, int len);
|
||||
void tls_certificate_set_priv(struct TLSCertificate *cert, const unsigned char *val, int len);
|
||||
void tls_certificate_set_sign_key(struct TLSCertificate *cert, const unsigned char *val, int len);
|
||||
char *tls_certificate_to_string(struct TLSCertificate *cert, char *buffer, int len);
|
||||
void tls_certificate_set_exponent(struct TLSCertificate *cert, const unsigned char *val, int len);
|
||||
void tls_certificate_set_serial(struct TLSCertificate *cert, const unsigned char *val, int len);
|
||||
void tls_certificate_set_algorithm(unsigned int *algorithm, const unsigned char *val, int len);
|
||||
void tls_destroy_certificate(struct TLSCertificate *cert);
|
||||
struct TLSPacket *tls_create_packet(struct TLSContext *context, unsigned char type, unsigned short version, int payload_size_hint);
|
||||
void tls_destroy_packet(struct TLSPacket *packet);
|
||||
void tls_packet_update(struct TLSPacket *packet);
|
||||
int tls_packet_append(struct TLSPacket *packet, unsigned char *buf, unsigned int len);
|
||||
int tls_packet_uint8(struct TLSPacket *packet, unsigned char i);
|
||||
int tls_packet_uint16(struct TLSPacket *packet, unsigned short i);
|
||||
int tls_packet_uint32(struct TLSPacket *packet, unsigned int i);
|
||||
int tls_packet_uint24(struct TLSPacket *packet, unsigned int i);
|
||||
int tls_random(unsigned char *key, int len);
|
||||
const unsigned char *tls_get_write_buffer(struct TLSContext *context, unsigned int *outlen);
|
||||
void tls_buffer_clear(struct TLSContext *context);
|
||||
int tls_established(struct TLSContext *context);
|
||||
void tls_read_clear(struct TLSContext *context);
|
||||
int tls_read(struct TLSContext *context, unsigned char *buf, unsigned int size);
|
||||
struct TLSContext *tls_create_context(unsigned char is_server, unsigned short version);
|
||||
const struct ECCCurveParameters *tls_set_curve(struct TLSContext *context, const struct ECCCurveParameters *curve);
|
||||
struct TLSContext *tls_accept(struct TLSContext *context);
|
||||
int tls_set_default_dhe_pg(struct TLSContext *context, const char *p_hex_str, const char *g_hex_str);
|
||||
void tls_destroy_context(struct TLSContext *context);
|
||||
int tls_cipher_supported(struct TLSContext *context, unsigned short cipher);
|
||||
int tls_cipher_is_fs(struct TLSContext *context, unsigned short cipher);
|
||||
int tls_choose_cipher(struct TLSContext *context, const unsigned char *buf, int buf_len, int *scsv_set);
|
||||
int tls_cipher_is_ephemeral(struct TLSContext *context);
|
||||
const char *tls_cipher_name(struct TLSContext *context);
|
||||
int tls_is_ecdsa(struct TLSContext *context);
|
||||
struct TLSPacket *tls_build_client_key_exchange(struct TLSContext *context);
|
||||
struct TLSPacket *tls_build_server_key_exchange(struct TLSContext *context, int method);
|
||||
struct TLSPacket *tls_build_hello(struct TLSContext *context);
|
||||
struct TLSPacket *tls_certificate_request(struct TLSContext *context);
|
||||
struct TLSPacket *tls_build_verify_request(struct TLSContext *context);
|
||||
int tls_parse_hello(struct TLSContext *context, const unsigned char *buf, int buf_len, unsigned int *write_packets, unsigned int *dtls_verified);
|
||||
int tls_parse_certificate(struct TLSContext *context, const unsigned char *buf, int buf_len, int is_client);
|
||||
int tls_parse_server_key_exchange(struct TLSContext *context, const unsigned char *buf, int buf_len);
|
||||
int tls_parse_client_key_exchange(struct TLSContext *context, const unsigned char *buf, int buf_len);
|
||||
int tls_parse_server_hello_done(struct TLSContext *context, const unsigned char *buf, int buf_len);
|
||||
int tls_parse_finished(struct TLSContext *context, const unsigned char *buf, int buf_len, unsigned int *write_packets);
|
||||
int tls_parse_verify(struct TLSContext *context, const unsigned char *buf, int buf_len);
|
||||
int tls_parse_payload(struct TLSContext *context, const unsigned char *buf, int buf_len, tls_validation_function certificate_verify);
|
||||
int tls_parse_message(struct TLSContext *context, unsigned char *buf, int buf_len, tls_validation_function certificate_verify);
|
||||
int tls_certificate_verify_signature(struct TLSCertificate *cert, struct TLSCertificate *parent);
|
||||
int tls_certificate_chain_is_valid(struct TLSCertificate **certificates, int len);
|
||||
int tls_certificate_chain_is_valid_root(struct TLSContext *context, struct TLSCertificate **certificates, int len);
|
||||
int tls_load_certificates(struct TLSContext *context, const unsigned char *pem_buffer, int pem_size);
|
||||
int tls_load_private_key(struct TLSContext *context, const unsigned char *pem_buffer, int pem_size);
|
||||
struct TLSPacket *tls_build_certificate(struct TLSContext *context);
|
||||
struct TLSPacket *tls_build_finished(struct TLSContext *context);
|
||||
struct TLSPacket *tls_build_change_cipher_spec(struct TLSContext *context);
|
||||
struct TLSPacket *tls_build_done(struct TLSContext *context);
|
||||
struct TLSPacket *tls_build_message(struct TLSContext *context, unsigned char *data, unsigned int len);
|
||||
int tls_client_connect(struct TLSContext *context);
|
||||
int tls_write(struct TLSContext *context, unsigned char *data, unsigned int len);
|
||||
struct TLSPacket *tls_build_alert(struct TLSContext *context, char critical, unsigned char code);
|
||||
int tls_consume_stream(struct TLSContext *context, const unsigned char *buf, int buf_len, tls_validation_function certificate_verify);
|
||||
void tls_close_notify(struct TLSContext *context);
|
||||
void tls_alert(struct TLSContext *context, unsigned char critical, int code);
|
||||
int tls_pending(struct TLSContext *context);
|
||||
void tls_make_exportable(struct TLSContext *context, unsigned char exportable_flag);
|
||||
int tls_export_context(struct TLSContext *context, unsigned char *buffer, unsigned int buf_len, unsigned char small_version);
|
||||
struct TLSContext *tls_import_context(unsigned char *buffer, unsigned int buf_len);
|
||||
int tls_is_broken(struct TLSContext *context);
|
||||
int tls_request_client_certificate(struct TLSContext *context);
|
||||
int tls_client_verified(struct TLSContext *context);
|
||||
const char *tls_sni(struct TLSContext *context);
|
||||
int tls_sni_set(struct TLSContext *context, const char *sni);
|
||||
int tls_load_root_certificates(struct TLSContext *context, const unsigned char *pem_buffer, int pem_size);
|
||||
int tls_default_verify(struct TLSContext *context, struct TLSCertificate **certificate_chain, int len);
|
||||
void tls_print_certificate(const char *fname);
|
||||
|
||||
#ifdef SSL_COMPATIBLE_INTERFACE
|
||||
#define SSL_SERVER_RSA_CERT 1
|
||||
#define SSL_SERVER_RSA_KEY 2
|
||||
typedef struct TLSContext SSL_CTX;
|
||||
typedef struct TLSContext SSL;
|
||||
|
||||
#define SSL_FILETYPE_PEM 1
|
||||
#define SSL_VERIFY_NONE 0
|
||||
#define SSL_VERIFY_PEER 1
|
||||
#define SSL_VERIFY_FAIL_IF_NO_PEER_CERT 2
|
||||
#define SSL_VERIFY_CLIENT_ONCE 3
|
||||
|
||||
typedef struct {
|
||||
int fd;
|
||||
tls_validation_function certificate_verify;
|
||||
void *user_data;
|
||||
} SSLUserData;
|
||||
|
||||
int SSL_library_init();
|
||||
void SSL_load_error_strings();
|
||||
void OpenSSL_add_all_algorithms();
|
||||
void OpenSSL_add_all_ciphers();
|
||||
void OpenSSL_add_all_digests();
|
||||
void EVP_cleanup();
|
||||
|
||||
int SSLv3_server_method();
|
||||
int SSLv3_client_method();
|
||||
struct TLSContext *SSL_new(struct TLSContext *context);
|
||||
int SSL_CTX_use_certificate_file(struct TLSContext *context, const char *filename, int dummy);
|
||||
int SSL_CTX_use_PrivateKey_file(struct TLSContext *context, const char *filename, int dummy);
|
||||
int SSL_CTX_check_private_key(struct TLSContext *context);
|
||||
struct TLSContext *SSL_CTX_new(int method);
|
||||
void SSL_free(struct TLSContext *context);
|
||||
void SSL_CTX_free(struct TLSContext *context);
|
||||
int SSL_get_error(struct TLSContext *context, int ret);
|
||||
int SSL_set_fd(struct TLSContext *context, int socket);
|
||||
void *SSL_set_userdata(struct TLSContext *context, void *data);
|
||||
void *SSL_userdata(struct TLSContext *context);
|
||||
int SSL_CTX_root_ca(struct TLSContext *context, const char *pem_filename);
|
||||
void SSL_CTX_set_verify(struct TLSContext *context, int mode, tls_validation_function verify_callback);
|
||||
int SSL_accept(struct TLSContext *context);
|
||||
int SSL_connect(struct TLSContext *context);
|
||||
int SSL_shutdown(struct TLSContext *context);
|
||||
int SSL_write(struct TLSContext *context, void *buf, unsigned int len);
|
||||
int SSL_read(struct TLSContext *context, void *buf, unsigned int len);
|
||||
int SSL_pending(struct TLSContext *context);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
1555
arlib/socket/uuu.cpp
Normal file
1555
arlib/socket/uuu.cpp
Normal file
File diff suppressed because it is too large
Load Diff
141
arlib/socket/wolfssl-lib.c
Normal file
141
arlib/socket/wolfssl-lib.c
Normal file
@@ -0,0 +1,141 @@
|
||||
#ifdef ARLIB_SSL_WOLFSSL_SP
|
||||
//I'll have to #include the parts of WolfSSL I need
|
||||
//it's easier in preprocessor than in makefile
|
||||
|
||||
#define DEBUG_WOLFSSL
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
//#define NO_WOLFSSL_MEMORY // use malloc like a sane program
|
||||
//#define NO_WOLFSSL_DIR // we scan the directories ourelves
|
||||
//#define WOLFSSL_USER_IO // we set our own read/write callbacks
|
||||
|
||||
#ifdef _WIN32
|
||||
#define USE_WINDOWS_API
|
||||
#else
|
||||
#define WOLFSSL_PTHREADS
|
||||
#endif
|
||||
|
||||
//#ifndef ARLIB_THREAD
|
||||
//#define SINGLE_THREADED
|
||||
//#endif
|
||||
|
||||
//got these from ./configure
|
||||
#define HAVE_THREAD_LS
|
||||
#define HAVE_AESGCM
|
||||
#define WOLFSSL_SHA512
|
||||
#define WOLFSSL_SHA384
|
||||
#define NO_DSA
|
||||
#define HAVE_ECC
|
||||
#define TFM_ECC256
|
||||
#define ECC_SHAMIR
|
||||
#define NO_RC4
|
||||
#define NO_HC128
|
||||
#define NO_RABBIT
|
||||
#define HAVE_POLY1305
|
||||
#define HAVE_ONE_TIME_AUTH
|
||||
#define HAVE_CHACHA
|
||||
#define HAVE_HASHDRBG
|
||||
#define HAVE_TLS_EXTENSIONS
|
||||
#define HAVE_SUPPORTED_CURVES
|
||||
#define NO_PSK
|
||||
#define NO_MD4
|
||||
#define NO_PWDBASED
|
||||
#define USE_FAST_MATH
|
||||
#define WOLFSSL_X86_64_BUILD
|
||||
#define HAVE___UINT128_T
|
||||
|
||||
#include "wolfssl-3.9.0/src/crl.c"
|
||||
#include "wolfssl-3.9.0/src/internal.c"
|
||||
#define c16toa c16toa_b // these functions are copypasted. should be in a header
|
||||
#define c32toa c32toa_b
|
||||
#define ato16 ato16_b
|
||||
#define c24to32 c24to32_b
|
||||
#define GetSEQIncrement GetSEQIncrement_b
|
||||
#include "wolfssl-3.9.0/src/io.c"
|
||||
#include "wolfssl-3.9.0/src/keys.c"
|
||||
#include "wolfssl-3.9.0/src/ocsp.c"
|
||||
#include "wolfssl-3.9.0/src/sniffer.c"
|
||||
#include "wolfssl-3.9.0/src/ssl.c"
|
||||
#include "wolfssl-3.9.0/src/tls.c"
|
||||
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/aes.c"
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/arc4.c"
|
||||
//#include "wolfssl-3.9.0/wolfcrypt/src/asm.c"
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/asn.c"
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/blake2b.c"
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/camellia.c"
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/chacha20_poly1305.c"
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/chacha.c"
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/coding.c"
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/compress.c"
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/curve25519.c"
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/des3.c"
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/dh.c"
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/dsa.c"
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/ecc.c"
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/ecc_fp.c"
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/ed25519.c"
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/error.c"
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/fe_low_mem.c"
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/fe_operations.c"
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/ge_low_mem.c"
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/ge_operations.c"
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/hash.c"
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/hc128.c"
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/hmac.c"
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/idea.c"
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/integer.c"
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/logging.c"
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/md2.c"
|
||||
#define Transform Transform_md4 // several functions and macros exist multiple times
|
||||
#define AddLength AddLength_md4
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/md4.c"
|
||||
#undef Transform
|
||||
#undef AddLength
|
||||
#define Transform Transform_md5
|
||||
#define AddLength AddLength_md5
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/md5.c"
|
||||
#undef Transform
|
||||
#undef AddLength
|
||||
#undef XTRANSFORM
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/memory.c"
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/misc.c"
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/pkcs7.c"
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/poly1305.c"
|
||||
#undef LO
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/pwdbased.c"
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/rabbit.c"
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/random.c"
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/ripemd.c"
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/rsa.c"
|
||||
#define Transform Transform_sha256
|
||||
#define AddLength AddLength_sha256
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/sha256.c"
|
||||
#undef Ch
|
||||
#undef Maj
|
||||
#undef R
|
||||
#undef R2
|
||||
#undef blk0
|
||||
#undef Transform
|
||||
#undef AddLength
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/sha512.c"
|
||||
#undef Ch
|
||||
#undef Maj
|
||||
#undef R
|
||||
#undef R2
|
||||
#undef blk0
|
||||
#undef XTRANSFORM
|
||||
#define _Transform _Transform_sha
|
||||
#define AddLength AddLength_sha
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/sha.c"
|
||||
#undef Transform
|
||||
#undef AddLength
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/signature.c"
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/srp.c"
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/tfm.c"
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/wc_encrypt.c"
|
||||
#include "wolfssl-3.9.0/wolfcrypt/src/wc_port.c"
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user