- IEC 61850/MMS: integrated TLS for MMS client/server
parent
9c946eeb40
commit
570ca71570
@ -0,0 +1,59 @@
|
|||||||
|
#ifndef MBEDTLS_CONFIG_H
|
||||||
|
#define MBEDTLS_CONFIG_H
|
||||||
|
|
||||||
|
/* System support */
|
||||||
|
#define MBEDTLS_HAVE_ASM
|
||||||
|
#define MBEDTLS_HAVE_TIME
|
||||||
|
#define MBEDTLS_NO_UDBL_DIVISION
|
||||||
|
#define MBEDTLS_PLATFORM_C
|
||||||
|
#define MBEDTLS_DEBUG_C
|
||||||
|
|
||||||
|
/* mbed TLS feature support */
|
||||||
|
#define MBEDTLS_CIPHER_MODE_CBC
|
||||||
|
#define MBEDTLS_PKCS1_V15
|
||||||
|
#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
|
||||||
|
#define MBEDTLS_SSL_PROTO_TLS1_1
|
||||||
|
#define MBEDTLS_SSL_PROTO_TLS1
|
||||||
|
#define MBEDTLS_SSL_RENEGOTIATION
|
||||||
|
|
||||||
|
#define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES
|
||||||
|
|
||||||
|
/* mbed TLS modules */
|
||||||
|
#define MBEDTLS_AES_C
|
||||||
|
#define MBEDTLS_ASN1_PARSE_C
|
||||||
|
#define MBEDTLS_ASN1_WRITE_C
|
||||||
|
#define MBEDTLS_BIGNUM_C
|
||||||
|
#define MBEDTLS_CIPHER_C
|
||||||
|
#define MBEDTLS_CTR_DRBG_C
|
||||||
|
//#define MBEDTLS_DES_C
|
||||||
|
#define MBEDTLS_ENTROPY_C
|
||||||
|
#define MBEDTLS_MD_C
|
||||||
|
#define MBEDTLS_MD5_C
|
||||||
|
#define MBEDTLS_NET_C
|
||||||
|
#define MBEDTLS_OID_C
|
||||||
|
#define MBEDTLS_PK_C
|
||||||
|
#define MBEDTLS_PK_PARSE_C
|
||||||
|
#define MBEDTLS_RSA_C
|
||||||
|
#define MBEDTLS_SHA1_C
|
||||||
|
#define MBEDTLS_SHA256_C
|
||||||
|
#define MBEDTLS_SSL_CLI_C
|
||||||
|
#define MBEDTLS_SSL_SRV_C
|
||||||
|
#define MBEDTLS_SSL_TLS_C
|
||||||
|
#define MBEDTLS_X509_CRT_PARSE_C
|
||||||
|
#define MBEDTLS_X509_USE_C
|
||||||
|
#define MBEDTLS_SSL_CACHE_C
|
||||||
|
|
||||||
|
/* For test certificates */
|
||||||
|
#define MBEDTLS_BASE64_C
|
||||||
|
#define MBEDTLS_CERTS_C
|
||||||
|
#define MBEDTLS_PEM_PARSE_C
|
||||||
|
|
||||||
|
#define MBEDTLS_PKCS12_C
|
||||||
|
#define MBEDTLS_PKCS5_C
|
||||||
|
|
||||||
|
/* For testing with compat.sh */
|
||||||
|
#define MBEDTLS_FS_IO
|
||||||
|
|
||||||
|
#include "mbedtls/check_config.h"
|
||||||
|
|
||||||
|
#endif /* MBEDTLS_CONFIG_H */
|
@ -0,0 +1,497 @@
|
|||||||
|
/*
|
||||||
|
* tls_mbedtls.c
|
||||||
|
*
|
||||||
|
* TLS API for TCP/IP protocol stacks
|
||||||
|
*
|
||||||
|
* Copyright 2017 MZ Automation GmbH
|
||||||
|
*
|
||||||
|
* Implementation of the TLS abstraction layer for mbedtls
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "tls_api.h"
|
||||||
|
#include "hal_thread.h"
|
||||||
|
#include "lib_memory.h"
|
||||||
|
#include "linked_list.h"
|
||||||
|
|
||||||
|
//#include "mbedtls/config.h"
|
||||||
|
#include "mbedtls/platform.h"
|
||||||
|
#include "mbedtls/entropy.h"
|
||||||
|
#include "mbedtls/ctr_drbg.h"
|
||||||
|
#include "mbedtls/certs.h"
|
||||||
|
#include "mbedtls/x509.h"
|
||||||
|
#include "mbedtls/ssl.h"
|
||||||
|
#include "mbedtls/net_sockets.h"
|
||||||
|
#include "mbedtls/error.h"
|
||||||
|
#include "mbedtls/debug.h"
|
||||||
|
|
||||||
|
#define CONFIG_DEBUG_TLS 0
|
||||||
|
|
||||||
|
#if (CONFIG_DEBUG_TLS == 1)
|
||||||
|
#define DEBUG_PRINT(appId, fmt, ...) fprintf(stderr, "%s: " fmt, appId, ## __VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define DEBUG_PRINT(fmt, ...) {do {} while(0);}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
struct sTLSConfiguration {
|
||||||
|
mbedtls_entropy_context entropy;
|
||||||
|
mbedtls_ctr_drbg_context ctr_drbg;
|
||||||
|
|
||||||
|
mbedtls_x509_crt ownCertificate;
|
||||||
|
mbedtls_pk_context ownKey;
|
||||||
|
|
||||||
|
mbedtls_x509_crt cacerts;
|
||||||
|
|
||||||
|
mbedtls_ssl_config conf;
|
||||||
|
LinkedList /* <mbedtls_x509_crt*> */ allowedCertificates;
|
||||||
|
|
||||||
|
bool chainValidation;
|
||||||
|
bool allowOnlyKnownCertificates;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sTLSSocket {
|
||||||
|
mbedtls_ssl_context ssl;
|
||||||
|
Socket socket;
|
||||||
|
mbedtls_ssl_config conf;
|
||||||
|
TLSConfiguration tlsConfig;
|
||||||
|
bool storePeerCert;
|
||||||
|
uint8_t* peerCert;
|
||||||
|
int peerCertLength;
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool
|
||||||
|
compareCertificates(mbedtls_x509_crt *crt1, mbedtls_x509_crt *crt2)
|
||||||
|
{
|
||||||
|
if (crt1 != NULL && crt2 != NULL) {
|
||||||
|
|
||||||
|
if (crt1->sig.len == crt2->sig.len) {
|
||||||
|
if (memcmp(crt1->sig.p, crt2->sig.p, crt1->sig.len) == 0)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
verifyCertificate (void* parameter, mbedtls_x509_crt *crt, int certificate_depth, uint32_t *flags)
|
||||||
|
{
|
||||||
|
TLSSocket self = (TLSSocket) parameter;
|
||||||
|
|
||||||
|
DEBUG_PRINT("TLS", "Verify cert: depth %i\n", certificate_depth);
|
||||||
|
|
||||||
|
DEBUG_PRINT("TLS", " flags: %08x\n", *flags);
|
||||||
|
|
||||||
|
char buffer[1024];
|
||||||
|
|
||||||
|
mbedtls_x509_crt_info(buffer, 1023, " ", crt);
|
||||||
|
|
||||||
|
DEBUG_PRINT("TLS", "%s\n", buffer);
|
||||||
|
|
||||||
|
if (self->tlsConfig->chainValidation == false) {
|
||||||
|
if (certificate_depth != 0)
|
||||||
|
*flags = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (certificate_depth == 0) {
|
||||||
|
if (self->tlsConfig->allowOnlyKnownCertificates) {
|
||||||
|
|
||||||
|
DEBUG_PRINT("TLS", "Check against list of allowed certs\n");
|
||||||
|
|
||||||
|
bool certMatches = false;
|
||||||
|
|
||||||
|
LinkedList certList = LinkedList_getNext(self->tlsConfig->allowedCertificates);
|
||||||
|
|
||||||
|
while (certList) {
|
||||||
|
mbedtls_x509_crt* allowedCert = (mbedtls_x509_crt*) LinkedList_getData(certList);
|
||||||
|
|
||||||
|
DEBUG_PRINT("TLS", "Compare With:\n");
|
||||||
|
mbedtls_x509_crt_info(buffer, 1023, " ", allowedCert);
|
||||||
|
DEBUG_PRINT("TLS", "%s\n", buffer);
|
||||||
|
|
||||||
|
if (compareCertificates(allowedCert, crt)) {
|
||||||
|
certMatches = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
certList = LinkedList_getNext(certList);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (certMatches)
|
||||||
|
*flags = 0;
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self->storePeerCert) {
|
||||||
|
|
||||||
|
if (*flags == 0) {
|
||||||
|
|
||||||
|
self->peerCertLength = crt->raw.len;
|
||||||
|
self->peerCert = (uint8_t*) GLOBAL_MALLOC(self->peerCertLength);
|
||||||
|
memcpy(self->peerCert, crt->raw.p, self->peerCertLength);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
TLSConfiguration
|
||||||
|
TLSConfiguration_create()
|
||||||
|
{
|
||||||
|
TLSConfiguration self = (TLSConfiguration) GLOBAL_MALLOC(sizeof(struct sTLSConfiguration));
|
||||||
|
|
||||||
|
if (self != NULL) {
|
||||||
|
mbedtls_ssl_config_init( &(self->conf) );
|
||||||
|
mbedtls_x509_crt_init( &(self->ownCertificate) );
|
||||||
|
mbedtls_x509_crt_init( &(self->cacerts));
|
||||||
|
mbedtls_pk_init( &(self->ownKey) );
|
||||||
|
mbedtls_entropy_init( &(self->entropy) );
|
||||||
|
mbedtls_ctr_drbg_init( &(self->ctr_drbg) );
|
||||||
|
|
||||||
|
//WARINING is fixed to server!
|
||||||
|
mbedtls_ssl_config_defaults( &(self->conf),
|
||||||
|
MBEDTLS_SSL_IS_SERVER,
|
||||||
|
MBEDTLS_SSL_TRANSPORT_STREAM,
|
||||||
|
MBEDTLS_SSL_PRESET_DEFAULT );
|
||||||
|
|
||||||
|
mbedtls_ctr_drbg_seed( &(self->ctr_drbg), mbedtls_entropy_func, &(self->entropy), NULL, 0);
|
||||||
|
mbedtls_ssl_conf_rng( &(self->conf), mbedtls_ctr_drbg_random, &(self->ctr_drbg) );
|
||||||
|
|
||||||
|
mbedtls_ssl_conf_authmode(&(self->conf), MBEDTLS_SSL_VERIFY_REQUIRED);
|
||||||
|
|
||||||
|
mbedtls_ssl_conf_renegotiation(&(self->conf), MBEDTLS_SSL_RENEGOTIATION_ENABLED);
|
||||||
|
|
||||||
|
//static int hashes[] = {3,4,5,6,7,8,0};
|
||||||
|
// mbedtls_ssl_conf_sig_hashes(&(self->conf), hashes);
|
||||||
|
|
||||||
|
self->allowedCertificates = LinkedList_create();
|
||||||
|
|
||||||
|
/* default behavior is to allow all certificates that are signed by the CA */
|
||||||
|
self->chainValidation = true;
|
||||||
|
self->allowOnlyKnownCertificates = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TLSConfiguration_setClientMode(TLSConfiguration self)
|
||||||
|
{
|
||||||
|
self->conf.endpoint = MBEDTLS_SSL_IS_CLIENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TLSConfiguration_setChainValidation(TLSConfiguration self, bool value)
|
||||||
|
{
|
||||||
|
self->chainValidation = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TLSConfiguration_setAllowOnlyKnownCertificates(TLSConfiguration self, bool value)
|
||||||
|
{
|
||||||
|
self->allowOnlyKnownCertificates = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
TLSConfiguration_setOwnCertificate(TLSConfiguration self, uint8_t* certificate, int certLen)
|
||||||
|
{
|
||||||
|
int ret = mbedtls_x509_crt_parse(&(self->ownCertificate), certificate, certLen);
|
||||||
|
|
||||||
|
if (ret != 0)
|
||||||
|
printf("mbedtls_x509_crt_parse returned %d\n", ret);
|
||||||
|
|
||||||
|
return (ret == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
TLSConfiguration_setOwnCertificateFromFile(TLSConfiguration self, const char* filename)
|
||||||
|
{
|
||||||
|
int ret = mbedtls_x509_crt_parse_file(&(self->ownCertificate), filename);
|
||||||
|
|
||||||
|
if (ret != 0)
|
||||||
|
DEBUG_PRINT("TLS", "mbedtls_x509_crt_parse_file returned %d\n", ret);
|
||||||
|
|
||||||
|
return (ret == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
TLSConfiguration_setOwnKey(TLSConfiguration self, uint8_t* key, int keyLen, const char* keyPassword)
|
||||||
|
{
|
||||||
|
int ret = mbedtls_pk_parse_key(&(self->ownKey), key, keyLen, (const uint8_t*) keyPassword, (keyPassword == NULL) ? 0 : strlen(keyPassword));
|
||||||
|
|
||||||
|
if (ret != 0)
|
||||||
|
DEBUG_PRINT("TLS", "mbedtls_pk_parse_key returned %d\n", ret);
|
||||||
|
|
||||||
|
return (ret == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
TLSConfiguration_setOwnKeyFromFile(TLSConfiguration self, const char* filename, const char* keyPassword)
|
||||||
|
{
|
||||||
|
int ret = mbedtls_pk_parse_keyfile(&(self->ownKey), filename, keyPassword);
|
||||||
|
|
||||||
|
if (ret != 0)
|
||||||
|
DEBUG_PRINT("TLS", "mbedtls_pk_parse_keyfile returned %d\n", ret);
|
||||||
|
|
||||||
|
return (ret == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
TLSConfiguration_addAllowedCertificate(TLSConfiguration self, uint8_t* certificate, int certLen)
|
||||||
|
{
|
||||||
|
mbedtls_x509_crt* cert = (mbedtls_x509_crt*) GLOBAL_CALLOC(1, sizeof(mbedtls_x509_crt));
|
||||||
|
|
||||||
|
int ret = mbedtls_x509_crt_parse(cert, certificate, certLen);
|
||||||
|
|
||||||
|
if (ret == 0) {
|
||||||
|
LinkedList_add(self->allowedCertificates, cert);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
GLOBAL_FREEMEM(cert);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
TLSConfiguration_addAllowedCertificateFromFile(TLSConfiguration self, const char* filename)
|
||||||
|
{
|
||||||
|
mbedtls_x509_crt* cert = (mbedtls_x509_crt*) GLOBAL_CALLOC(1, sizeof(mbedtls_x509_crt));
|
||||||
|
|
||||||
|
int ret = mbedtls_x509_crt_parse_file(cert, filename);
|
||||||
|
|
||||||
|
if (ret == 0) {
|
||||||
|
LinkedList_add(self->allowedCertificates, cert);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
GLOBAL_FREEMEM(cert);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
TLSConfiguration_addCACertificate(TLSConfiguration self, uint8_t* certificate, int certLen)
|
||||||
|
{
|
||||||
|
int ret = mbedtls_x509_crt_parse(&(self->cacerts), certificate, certLen);
|
||||||
|
|
||||||
|
if (ret != 0) {
|
||||||
|
DEBUG_PRINT("TLS", "mbedtls_x509_crt_parse returned %d\n", ret);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (ret == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
TLSConfiguration_addCACertificateFromFile(TLSConfiguration self, const char* filename)
|
||||||
|
{
|
||||||
|
int ret = mbedtls_x509_crt_parse_file(&(self->cacerts), filename);
|
||||||
|
|
||||||
|
if (ret != 0)
|
||||||
|
DEBUG_PRINT("TLS", "mbedtls_x509_crt_parse returned %d\n", ret);
|
||||||
|
|
||||||
|
return (ret == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TLSConfiguration_destroy(TLSConfiguration self)
|
||||||
|
{
|
||||||
|
mbedtls_x509_crt_free(&(self->ownCertificate));
|
||||||
|
mbedtls_x509_crt_free(&(self->cacerts));
|
||||||
|
mbedtls_pk_free(&(self->ownKey));
|
||||||
|
mbedtls_ssl_config_free(&(self->conf));
|
||||||
|
|
||||||
|
LinkedList certElem = LinkedList_getNext(self->allowedCertificates);
|
||||||
|
|
||||||
|
while (certElem) {
|
||||||
|
mbedtls_x509_crt* cert = (mbedtls_x509_crt*) LinkedList_getData(certElem);
|
||||||
|
|
||||||
|
mbedtls_x509_crt_free(cert);
|
||||||
|
|
||||||
|
certElem = LinkedList_getNext(certElem);
|
||||||
|
}
|
||||||
|
|
||||||
|
LinkedList_destroy(self->allowedCertificates);
|
||||||
|
|
||||||
|
GLOBAL_FREEMEM(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
readFunction(void* ctx, unsigned char* buf, size_t len)
|
||||||
|
{
|
||||||
|
int ret = Socket_read((Socket) ctx, buf, len);
|
||||||
|
|
||||||
|
if ((ret == 0) && (len > 0))
|
||||||
|
return MBEDTLS_ERR_SSL_WANT_READ;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
TLSSocket
|
||||||
|
TLSSocket_create(Socket socket, TLSConfiguration configuration, bool storeClientCert)
|
||||||
|
{
|
||||||
|
TLSSocket self = (TLSSocket) GLOBAL_CALLOC(1, sizeof(struct sTLSSocket));
|
||||||
|
|
||||||
|
if (self != NULL) {
|
||||||
|
|
||||||
|
self->socket = socket;
|
||||||
|
self->tlsConfig = configuration;
|
||||||
|
self->storePeerCert = storeClientCert;
|
||||||
|
self->peerCert = NULL;
|
||||||
|
self->peerCertLength = 0;
|
||||||
|
|
||||||
|
memcpy(&(self->conf), &(configuration->conf), sizeof(mbedtls_ssl_config));
|
||||||
|
|
||||||
|
mbedtls_ssl_conf_verify(&(self->conf), verifyCertificate, (void*) self);
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
mbedtls_ssl_conf_ca_chain( &(self->conf), &(configuration->cacerts), NULL );
|
||||||
|
|
||||||
|
ret = mbedtls_ssl_conf_own_cert( &(self->conf), &(configuration->ownCertificate), &(configuration->ownKey));
|
||||||
|
|
||||||
|
if (ret != 0)
|
||||||
|
DEBUG_PRINT("TLS", "mbedtls_ssl_conf_own_cert returned %d\n", ret);
|
||||||
|
|
||||||
|
ret = mbedtls_ssl_setup( &(self->ssl), &(self->conf) );
|
||||||
|
|
||||||
|
if (ret != 0)
|
||||||
|
DEBUG_PRINT("TLS", "mbedtls_ssl_setup returned %d\n", ret);
|
||||||
|
|
||||||
|
mbedtls_ssl_set_bio(&(self->ssl), socket, (mbedtls_ssl_send_t*) Socket_write,
|
||||||
|
(mbedtls_ssl_recv_t*) readFunction, NULL);
|
||||||
|
|
||||||
|
while( (ret = mbedtls_ssl_handshake(&(self->ssl)) ) != 0 )
|
||||||
|
{
|
||||||
|
if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
|
||||||
|
{
|
||||||
|
DEBUG_PRINT("TLS", "mbedtls_ssl_handshake returned %d\n\n", ret );
|
||||||
|
|
||||||
|
GLOBAL_FREEMEM(self);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t*
|
||||||
|
TLSSocket_getPeerCertificate(TLSSocket self, int* certSize)
|
||||||
|
{
|
||||||
|
if (certSize)
|
||||||
|
*certSize = self->peerCertLength;
|
||||||
|
|
||||||
|
return self->peerCert;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
TLSSocket_read(TLSSocket self, uint8_t* buf, int size)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
int len = size;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
ret = mbedtls_ssl_read( &(self->ssl), buf, len );
|
||||||
|
|
||||||
|
if( ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if( ret <= 0 )
|
||||||
|
{
|
||||||
|
switch( ret )
|
||||||
|
{
|
||||||
|
case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
|
||||||
|
DEBUG_PRINT("TLS", " connection was closed gracefully\n" );
|
||||||
|
len = -1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MBEDTLS_ERR_NET_CONN_RESET:
|
||||||
|
len = -1;
|
||||||
|
DEBUG_PRINT("TLS", " connection was reset by peer\n" );
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
DEBUG_PRINT("TLS", " mbedtls_ssl_read returned -0x%x\n", -ret );
|
||||||
|
len = -1; //TODO is this the correct return value?
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = ret;
|
||||||
|
|
||||||
|
if( ret > 0 )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
while( 1 );
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
TLSSocket_write(TLSSocket self, uint8_t* buf, int size)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
int len = size;
|
||||||
|
|
||||||
|
|
||||||
|
while( ( ret = mbedtls_ssl_write( &(self->ssl), buf, len ) ) <= 0 )
|
||||||
|
{
|
||||||
|
if( ret == MBEDTLS_ERR_NET_CONN_RESET )
|
||||||
|
{
|
||||||
|
DEBUG_PRINT("TLS", "peer closed the connection\n" );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
|
||||||
|
{
|
||||||
|
DEBUG_PRINT("TLS", "mbedtls_ssl_write returned %d\n", ret );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
len = ret;
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TLSSocket_close(TLSSocket self)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
//TODO add timeout?
|
||||||
|
|
||||||
|
while( ( ret = mbedtls_ssl_close_notify( &(self->ssl) ) ) < 0 )
|
||||||
|
{
|
||||||
|
if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
||||||
|
ret != MBEDTLS_ERR_SSL_WANT_WRITE )
|
||||||
|
{
|
||||||
|
DEBUG_PRINT("TLS", "mbedtls_ssl_close_notify returned %d\n", ret );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread_sleep(10);
|
||||||
|
|
||||||
|
mbedtls_ssl_config_free(&(self->conf));
|
||||||
|
mbedtls_ssl_free(&(self->ssl));
|
||||||
|
|
||||||
|
GLOBAL_FREEMEM(self);
|
||||||
|
}
|
@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
* tls_api.h
|
||||||
|
*
|
||||||
|
* TLS API for TCP/IP protocol stacks
|
||||||
|
*
|
||||||
|
* Copyright 2017 MZ Automation GmbH
|
||||||
|
*
|
||||||
|
* Abstraction layer for different TLS implementations
|
||||||
|
*
|
||||||
|
* Implementation connects the TLS API layer with the socket API layer
|
||||||
|
* and performs all TLS tasks like handshake, encryption/decryption.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SRC_TLS_TLS_API_H_
|
||||||
|
#define SRC_TLS_TLS_API_H_
|
||||||
|
|
||||||
|
#include "hal_socket.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct sTLSConfiguration* TLSConfiguration;
|
||||||
|
|
||||||
|
typedef struct sTLSSocket* TLSSocket;
|
||||||
|
|
||||||
|
TLSConfiguration
|
||||||
|
TLSConfiguration_create(void);
|
||||||
|
|
||||||
|
/* will be called by stack automatically */
|
||||||
|
void
|
||||||
|
TLSConfiguration_setClientMode(TLSConfiguration self);
|
||||||
|
|
||||||
|
void
|
||||||
|
TLSConfiguration_setChainValidation(TLSConfiguration self, bool value);
|
||||||
|
|
||||||
|
void
|
||||||
|
TLSConfiguration_setAllowOnlyKnownCertificates(TLSConfiguration self, bool value);
|
||||||
|
|
||||||
|
bool
|
||||||
|
TLSConfiguration_setOwnCertificate(TLSConfiguration self, uint8_t* certificate, int certLen);
|
||||||
|
|
||||||
|
bool
|
||||||
|
TLSConfiguration_setOwnCertificateFromFile(TLSConfiguration self, const char* filename);
|
||||||
|
|
||||||
|
bool
|
||||||
|
TLSConfiguration_setOwnKey(TLSConfiguration self, uint8_t* key, int keyLen, const char* keyPassword);
|
||||||
|
|
||||||
|
bool
|
||||||
|
TLSConfiguration_setOwnKeyFromFile(TLSConfiguration self, const char* filename, const char* keyPassword);
|
||||||
|
|
||||||
|
bool
|
||||||
|
TLSConfiguration_addAllowedCertificate(TLSConfiguration self, uint8_t* certifcate, int certLen);
|
||||||
|
|
||||||
|
bool
|
||||||
|
TLSConfiguration_addAllowedCertificateFromFile(TLSConfiguration self, const char* filename);
|
||||||
|
|
||||||
|
bool
|
||||||
|
TLSConfiguration_addCACertificate(TLSConfiguration self, uint8_t* certifcate, int certLen);
|
||||||
|
|
||||||
|
bool
|
||||||
|
TLSConfiguration_addCACertificateFromFile(TLSConfiguration self, const char* filename);
|
||||||
|
|
||||||
|
void
|
||||||
|
TLSConfiguration_destroy(TLSConfiguration self);
|
||||||
|
|
||||||
|
TLSSocket
|
||||||
|
TLSSocket_create(Socket socket, TLSConfiguration configuration, bool storeClientCert);
|
||||||
|
|
||||||
|
bool
|
||||||
|
TLSSocket_performHandshake(TLSSocket self);
|
||||||
|
|
||||||
|
uint8_t*
|
||||||
|
TLSSocket_getPeerCertificate(TLSSocket self, int* certSize);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief read from socket to local buffer (non-blocking)
|
||||||
|
*
|
||||||
|
* The function shall return immediately if no data is available. In this case
|
||||||
|
* the function returns 0. If an error happens the function shall return -1.
|
||||||
|
*
|
||||||
|
* Implementation of this function is MANDATORY
|
||||||
|
*
|
||||||
|
* NOTE: The behaviour of this function changed with version 0.8!
|
||||||
|
*
|
||||||
|
* \param self the client, connection or server socket instance
|
||||||
|
* \param buf the buffer where the read bytes are copied to
|
||||||
|
* \param size the maximum number of bytes to read (size of the provided buffer)
|
||||||
|
*
|
||||||
|
* \return the number of bytes read or -1 if an error occurred
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
TLSSocket_read(TLSSocket self, uint8_t* buf, int size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief send a message through the socket
|
||||||
|
*
|
||||||
|
* Implementation of this function is MANDATORY
|
||||||
|
*
|
||||||
|
* \param self client, connection or server socket instance
|
||||||
|
*
|
||||||
|
* \return number of bytes transmitted of -1 in case of an error
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
TLSSocket_write(TLSSocket self, uint8_t* buf, int size);
|
||||||
|
|
||||||
|
void
|
||||||
|
TLSSocket_close(TLSSocket self);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* SRC_TLS_TLS_API_H_ */
|
@ -0,0 +1,6 @@
|
|||||||
|
README
|
||||||
|
------
|
||||||
|
|
||||||
|
For TLS support with mbedtls download the source tarball of version 2.6.0 and extract here in the subfolder
|
||||||
|
|
||||||
|
mbedtls-2.6.0
|
Loading…
Reference in New Issue