Implemented TLS Alert handling
This commit is contained in:
@@ -6,6 +6,7 @@ libtls_la_SOURCES = \
|
|||||||
tls_protection.h tls_protection.c \
|
tls_protection.h tls_protection.c \
|
||||||
tls_compression.h tls_compression.c \
|
tls_compression.h tls_compression.c \
|
||||||
tls_fragmentation.h tls_fragmentation.c \
|
tls_fragmentation.h tls_fragmentation.c \
|
||||||
|
tls_alert.h tls_alert.c \
|
||||||
tls_crypto.h tls_crypto.c \
|
tls_crypto.h tls_crypto.c \
|
||||||
tls_prf.h tls_prf.c \
|
tls_prf.h tls_prf.c \
|
||||||
tls_reader.h tls_reader.c \
|
tls_reader.h tls_reader.c \
|
||||||
|
|||||||
+13
-5
@@ -106,6 +106,11 @@ struct private_tls_t {
|
|||||||
*/
|
*/
|
||||||
tls_fragmentation_t *fragmentation;
|
tls_fragmentation_t *fragmentation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TLS alert handler
|
||||||
|
*/
|
||||||
|
tls_alert_t *alert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TLS crypto helper context
|
* TLS crypto helper context
|
||||||
*/
|
*/
|
||||||
@@ -159,6 +164,7 @@ METHOD(tls_t, set_version, bool,
|
|||||||
case TLS_1_1:
|
case TLS_1_1:
|
||||||
case TLS_1_2:
|
case TLS_1_2:
|
||||||
this->version = version;
|
this->version = version;
|
||||||
|
this->protection->set_version(this->protection, version);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
case SSL_2_0:
|
case SSL_2_0:
|
||||||
case SSL_3_0:
|
case SSL_3_0:
|
||||||
@@ -196,6 +202,7 @@ METHOD(tls_t, destroy, void,
|
|||||||
this->peer->destroy(this->peer);
|
this->peer->destroy(this->peer);
|
||||||
this->server->destroy(this->server);
|
this->server->destroy(this->server);
|
||||||
DESTROY_IF(this->application);
|
DESTROY_IF(this->application);
|
||||||
|
this->alert->destroy(this->alert);
|
||||||
|
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
@@ -239,20 +246,21 @@ tls_t *tls_create(bool is_server, identification_t *server,
|
|||||||
);
|
);
|
||||||
|
|
||||||
this->crypto = tls_crypto_create(&this->public);
|
this->crypto = tls_crypto_create(&this->public);
|
||||||
|
this->alert = tls_alert_create();
|
||||||
if (is_server)
|
if (is_server)
|
||||||
{
|
{
|
||||||
this->handshake = &tls_server_create(&this->public, this->crypto,
|
this->handshake = &tls_server_create(&this->public, this->crypto,
|
||||||
this->server, this->peer)->handshake;
|
this->alert, this->server, this->peer)->handshake;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this->handshake = &tls_peer_create(&this->public, this->crypto,
|
this->handshake = &tls_peer_create(&this->public, this->crypto,
|
||||||
this->peer, this->server)->handshake;
|
this->alert, this->peer, this->server)->handshake;
|
||||||
}
|
}
|
||||||
this->fragmentation = tls_fragmentation_create(this->handshake,
|
this->fragmentation = tls_fragmentation_create(this->handshake, this->alert,
|
||||||
this->application);
|
this->application);
|
||||||
this->compression = tls_compression_create(this->fragmentation);
|
this->compression = tls_compression_create(this->fragmentation, this->alert);
|
||||||
this->protection = tls_protection_create(&this->public, this->compression);
|
this->protection = tls_protection_create(this->compression, this->alert);
|
||||||
this->crypto->set_protection(this->crypto, this->protection);
|
this->crypto->set_protection(this->crypto, this->protection);
|
||||||
|
|
||||||
return &this->public;
|
return &this->public;
|
||||||
|
|||||||
@@ -0,0 +1,221 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2010 Martin Willi
|
||||||
|
* Copyright (C) 2010 revosec AG
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2 of the License, or (at your
|
||||||
|
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "tls_alert.h"
|
||||||
|
|
||||||
|
#include <debug.h>
|
||||||
|
#include <utils/linked_list.h>
|
||||||
|
|
||||||
|
ENUM_BEGIN(tls_alert_desc_names, TLS_CLOSE_NOTIFY, TLS_CLOSE_NOTIFY,
|
||||||
|
"close notify",
|
||||||
|
);
|
||||||
|
ENUM_NEXT(tls_alert_desc_names, TLS_UNEXPECTED_MESSAGE, TLS_UNEXPECTED_MESSAGE,
|
||||||
|
TLS_CLOSE_NOTIFY,
|
||||||
|
"unexpected message",
|
||||||
|
);
|
||||||
|
ENUM_NEXT(tls_alert_desc_names, TLS_BAD_RECORD_MAC, TLS_RECORD_OVERFLOW,
|
||||||
|
TLS_UNEXPECTED_MESSAGE,
|
||||||
|
"bad record mac",
|
||||||
|
"decryption failed",
|
||||||
|
"record overflow",
|
||||||
|
);
|
||||||
|
ENUM_NEXT(tls_alert_desc_names, TLS_DECOMPRESSION_FAILURE, TLS_DECOMPRESSION_FAILURE,
|
||||||
|
TLS_RECORD_OVERFLOW,
|
||||||
|
"decompression_failure",
|
||||||
|
);
|
||||||
|
ENUM_NEXT(tls_alert_desc_names, TLS_HANDSHAKE_FAILURE, TLS_DECRYPT_ERROR,
|
||||||
|
TLS_DECOMPRESSION_FAILURE,
|
||||||
|
"handshake failure",
|
||||||
|
"no certificate",
|
||||||
|
"bad certificate",
|
||||||
|
"unsupported certificate",
|
||||||
|
"certificate revoked",
|
||||||
|
"certificate expired",
|
||||||
|
"certificate unknown",
|
||||||
|
"illegal parameter",
|
||||||
|
"unknown ca",
|
||||||
|
"access denied",
|
||||||
|
"decode error",
|
||||||
|
"decrypt error",
|
||||||
|
);
|
||||||
|
ENUM_NEXT(tls_alert_desc_names, TLS_EXPORT_RESTRICTION, TLS_EXPORT_RESTRICTION,
|
||||||
|
TLS_DECRYPT_ERROR,
|
||||||
|
"export restriction",
|
||||||
|
);
|
||||||
|
ENUM_NEXT(tls_alert_desc_names, TLS_PROTOCOL_VERSION, TLS_INSUFFICIENT_SECURITY,
|
||||||
|
TLS_EXPORT_RESTRICTION,
|
||||||
|
"protocol version",
|
||||||
|
"insufficient security",
|
||||||
|
);
|
||||||
|
ENUM_NEXT(tls_alert_desc_names, TLS_INTERNAL_ERROR, TLS_INTERNAL_ERROR,
|
||||||
|
TLS_INSUFFICIENT_SECURITY,
|
||||||
|
"internal error",
|
||||||
|
);
|
||||||
|
ENUM_NEXT(tls_alert_desc_names, TLS_USER_CANCELED, TLS_USER_CANCELED,
|
||||||
|
TLS_INTERNAL_ERROR,
|
||||||
|
"user canceled",
|
||||||
|
);
|
||||||
|
ENUM_NEXT(tls_alert_desc_names, TLS_NO_RENEGOTIATION, TLS_NO_RENEGOTIATION,
|
||||||
|
TLS_USER_CANCELED,
|
||||||
|
"no renegotiation",
|
||||||
|
);
|
||||||
|
ENUM_NEXT(tls_alert_desc_names, TLS_UNSUPPORTED_EXTENSION, TLS_UNSUPPORTED_EXTENSION,
|
||||||
|
TLS_NO_RENEGOTIATION,
|
||||||
|
"unsupported extension",
|
||||||
|
);
|
||||||
|
ENUM_END(tls_alert_desc_names, TLS_UNSUPPORTED_EXTENSION);
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct private_tls_alert_t private_tls_alert_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private data of an tls_alert_t object.
|
||||||
|
*/
|
||||||
|
struct private_tls_alert_t {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public tls_alert_t interface.
|
||||||
|
*/
|
||||||
|
tls_alert_t public;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Warning queue
|
||||||
|
*/
|
||||||
|
linked_list_t *warnings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do we have a fatal alert?
|
||||||
|
*/
|
||||||
|
bool fatal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Has the fatal alert been consumed?
|
||||||
|
*/
|
||||||
|
bool consumed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fatal alert discription
|
||||||
|
*/
|
||||||
|
tls_alert_desc_t desc;
|
||||||
|
};
|
||||||
|
|
||||||
|
METHOD(tls_alert_t, add, void,
|
||||||
|
private_tls_alert_t *this, tls_alert_level_t level,
|
||||||
|
tls_alert_desc_t desc)
|
||||||
|
{
|
||||||
|
if (level == TLS_FATAL)
|
||||||
|
{
|
||||||
|
if (!this->fatal)
|
||||||
|
{
|
||||||
|
this->desc = desc;
|
||||||
|
this->fatal = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->warnings->insert_last(this->warnings, (void*)(uintptr_t)desc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(tls_alert_t, get, bool,
|
||||||
|
private_tls_alert_t *this, tls_alert_level_t *level,
|
||||||
|
tls_alert_desc_t *desc)
|
||||||
|
{
|
||||||
|
if (this->fatal && !this->consumed)
|
||||||
|
{
|
||||||
|
this->consumed = TRUE;
|
||||||
|
*level = TLS_FATAL;
|
||||||
|
*desc = this->desc;
|
||||||
|
DBG1(DBG_TLS, "sending fatal TLS alert '%N'",
|
||||||
|
tls_alert_desc_names, this->desc);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uintptr_t warning;
|
||||||
|
|
||||||
|
if (this->warnings->remove_first(this->warnings,
|
||||||
|
(void**)&warning) == SUCCESS)
|
||||||
|
{
|
||||||
|
*level = TLS_WARNING;
|
||||||
|
*desc = warning;
|
||||||
|
DBG1(DBG_TLS, "sending TLS alert warning '%N'",
|
||||||
|
tls_alert_desc_names, warning);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(tls_alert_t, fatal, bool,
|
||||||
|
private_tls_alert_t *this)
|
||||||
|
{
|
||||||
|
return this->fatal;
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(tls_alert_t, process, status_t,
|
||||||
|
private_tls_alert_t *this, tls_alert_level_t level,
|
||||||
|
tls_alert_desc_t desc)
|
||||||
|
{
|
||||||
|
if (desc == TLS_CLOSE_NOTIFY)
|
||||||
|
{
|
||||||
|
DBG1(DBG_TLS, "received TLS close notify");
|
||||||
|
add(this, TLS_FATAL, TLS_CLOSE_NOTIFY);
|
||||||
|
return NEED_MORE;
|
||||||
|
}
|
||||||
|
switch (level)
|
||||||
|
{
|
||||||
|
case TLS_WARNING:
|
||||||
|
DBG1(DBG_TLS, "received TLS alert warning '%N'",
|
||||||
|
tls_alert_desc_names, desc);
|
||||||
|
return NEED_MORE;
|
||||||
|
case TLS_FATAL:
|
||||||
|
DBG1(DBG_TLS, "received fatal TLS alert '%N'",
|
||||||
|
tls_alert_desc_names, desc);
|
||||||
|
return FAILED;
|
||||||
|
default:
|
||||||
|
DBG1(DBG_TLS, "received unknown TLS alert '%N'",
|
||||||
|
tls_alert_desc_names, desc);
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(tls_alert_t, destroy, void,
|
||||||
|
private_tls_alert_t *this)
|
||||||
|
{
|
||||||
|
this->warnings->destroy(this->warnings);
|
||||||
|
free(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See header
|
||||||
|
*/
|
||||||
|
tls_alert_t *tls_alert_create()
|
||||||
|
{
|
||||||
|
private_tls_alert_t *this;
|
||||||
|
|
||||||
|
INIT(this,
|
||||||
|
.public = {
|
||||||
|
.add = _add,
|
||||||
|
.get = _get,
|
||||||
|
.fatal = _fatal,
|
||||||
|
.process = _process,
|
||||||
|
.destroy = _destroy,
|
||||||
|
},
|
||||||
|
.warnings = linked_list_create(),
|
||||||
|
);
|
||||||
|
|
||||||
|
return &this->public;
|
||||||
|
}
|
||||||
@@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2010 Martin Willi
|
||||||
|
* Copyright (C) 2010 revosec AG
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2 of the License, or (at your
|
||||||
|
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup tls_alert tls_alert
|
||||||
|
* @{ @ingroup libtls
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TLS_ALERT_H_
|
||||||
|
#define TLS_ALERT_H_
|
||||||
|
|
||||||
|
#include <library.h>
|
||||||
|
|
||||||
|
typedef struct tls_alert_t tls_alert_t;
|
||||||
|
typedef enum tls_alert_level_t tls_alert_level_t;
|
||||||
|
typedef enum tls_alert_desc_t tls_alert_desc_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Level of a TLS alert
|
||||||
|
*/
|
||||||
|
enum tls_alert_level_t {
|
||||||
|
TLS_WARNING = 1,
|
||||||
|
TLS_FATAL = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Description of a TLS alert
|
||||||
|
*/
|
||||||
|
enum tls_alert_desc_t {
|
||||||
|
TLS_CLOSE_NOTIFY = 0,
|
||||||
|
TLS_UNEXPECTED_MESSAGE = 10,
|
||||||
|
TLS_BAD_RECORD_MAC = 20,
|
||||||
|
TLS_DECRYPTION_FAILED = 21,
|
||||||
|
TLS_RECORD_OVERFLOW = 22,
|
||||||
|
TLS_DECOMPRESSION_FAILURE = 30,
|
||||||
|
TLS_HANDSHAKE_FAILURE = 40,
|
||||||
|
TLS_NO_CERTIFICATE = 41,
|
||||||
|
TLS_BAD_CERTIFICATE = 42,
|
||||||
|
TLS_UNSUPPORTED_CERTIFICATE = 43,
|
||||||
|
TLS_CERTIFICATE_REVOKED = 44,
|
||||||
|
TLS_CERTIFICATE_EXPIRED = 45,
|
||||||
|
TLS_CERTIFICATE_UNKNOWN = 46,
|
||||||
|
TLS_ILLEGAL_PARAMETER = 47,
|
||||||
|
TLS_UNKNOWN_CA = 48,
|
||||||
|
TLS_ACCESS_DENIED = 49,
|
||||||
|
TLS_DECODE_ERROR = 50,
|
||||||
|
TLS_DECRYPT_ERROR = 51,
|
||||||
|
TLS_EXPORT_RESTRICTION = 60,
|
||||||
|
TLS_PROTOCOL_VERSION = 70,
|
||||||
|
TLS_INSUFFICIENT_SECURITY = 71,
|
||||||
|
TLS_INTERNAL_ERROR = 80,
|
||||||
|
TLS_USER_CANCELED = 90,
|
||||||
|
TLS_NO_RENEGOTIATION = 100,
|
||||||
|
TLS_UNSUPPORTED_EXTENSION = 110,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enum names for alert descriptions
|
||||||
|
*/
|
||||||
|
extern enum_name_t *tls_alert_desc_names;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TLS alert handling.
|
||||||
|
*/
|
||||||
|
struct tls_alert_t {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an alert to the TLS alert queue, will be sent.
|
||||||
|
*
|
||||||
|
* @param level level of TLS alert
|
||||||
|
* @param description description of alert
|
||||||
|
*/
|
||||||
|
void (*add)(tls_alert_t *this, tls_alert_level_t level,
|
||||||
|
tls_alert_desc_t description);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an alert pushed to the alert queue, to send.
|
||||||
|
*
|
||||||
|
* @param level receives TLS alert level
|
||||||
|
* @param description receives TLS alert description
|
||||||
|
* @return TRUE if returned an alert
|
||||||
|
*/
|
||||||
|
bool (*get)(tls_alert_t *this, tls_alert_level_t *level,
|
||||||
|
tls_alert_desc_t *description);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Did a fatal alert occur?.
|
||||||
|
*
|
||||||
|
* @return TRUE if a fatal alert has occured
|
||||||
|
*/
|
||||||
|
bool (*fatal)(tls_alert_t *this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process a received TLS alert.
|
||||||
|
*
|
||||||
|
* @param level level of received alert
|
||||||
|
* @param description alert description
|
||||||
|
* @return status to pass down to TLS stack
|
||||||
|
*/
|
||||||
|
status_t (*process)(tls_alert_t *this, tls_alert_level_t level,
|
||||||
|
tls_alert_desc_t description);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy a tls_alert_t.
|
||||||
|
*/
|
||||||
|
void (*destroy)(tls_alert_t *this);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a tls_alert instance.
|
||||||
|
*/
|
||||||
|
tls_alert_t *tls_alert_create();
|
||||||
|
|
||||||
|
#endif /** TLS_ALERT_H_ @}*/
|
||||||
@@ -54,7 +54,8 @@ METHOD(tls_compression_t, destroy, void,
|
|||||||
/**
|
/**
|
||||||
* See header
|
* See header
|
||||||
*/
|
*/
|
||||||
tls_compression_t *tls_compression_create(tls_fragmentation_t *fragmentation)
|
tls_compression_t *tls_compression_create(tls_fragmentation_t *fragmentation,
|
||||||
|
tls_alert_t *alert)
|
||||||
{
|
{
|
||||||
private_tls_compression_t *this;
|
private_tls_compression_t *this;
|
||||||
|
|
||||||
|
|||||||
@@ -21,13 +21,14 @@
|
|||||||
#ifndef TLS_COMPRESSION_H_
|
#ifndef TLS_COMPRESSION_H_
|
||||||
#define TLS_COMPRESSION_H_
|
#define TLS_COMPRESSION_H_
|
||||||
|
|
||||||
typedef struct tls_compression_t tls_compression_t;
|
|
||||||
|
|
||||||
#include <library.h>
|
#include <library.h>
|
||||||
|
|
||||||
#include "tls.h"
|
#include "tls.h"
|
||||||
|
#include "tls_alert.h"
|
||||||
#include "tls_fragmentation.h"
|
#include "tls_fragmentation.h"
|
||||||
|
|
||||||
|
typedef struct tls_compression_t tls_compression_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TLS record protocol compression layer.
|
* TLS record protocol compression layer.
|
||||||
*/
|
*/
|
||||||
@@ -70,8 +71,10 @@ struct tls_compression_t {
|
|||||||
* Create a tls_compression instance.
|
* Create a tls_compression instance.
|
||||||
*
|
*
|
||||||
* @param fragmentation fragmentation layer of TLS stack
|
* @param fragmentation fragmentation layer of TLS stack
|
||||||
|
* @param alert TLS alert handler
|
||||||
* @return TLS compression layer.
|
* @return TLS compression layer.
|
||||||
*/
|
*/
|
||||||
tls_compression_t *tls_compression_create(tls_fragmentation_t *fragmentation);
|
tls_compression_t *tls_compression_create(tls_fragmentation_t *fragmentation,
|
||||||
|
tls_alert_t *alert);
|
||||||
|
|
||||||
#endif /** TLS_COMPRESSION_H_ @}*/
|
#endif /** TLS_COMPRESSION_H_ @}*/
|
||||||
|
|||||||
@@ -21,6 +21,18 @@
|
|||||||
|
|
||||||
typedef struct private_tls_fragmentation_t private_tls_fragmentation_t;
|
typedef struct private_tls_fragmentation_t private_tls_fragmentation_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alert state
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
/* no alert received/sent */
|
||||||
|
ALERT_NONE,
|
||||||
|
/* currently sending an alert */
|
||||||
|
ALERT_SENDING,
|
||||||
|
/* alert sent and out */
|
||||||
|
ALERT_SENT,
|
||||||
|
} alert_state_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private data of an tls_fragmentation_t object.
|
* Private data of an tls_fragmentation_t object.
|
||||||
*/
|
*/
|
||||||
@@ -36,6 +48,16 @@ struct private_tls_fragmentation_t {
|
|||||||
*/
|
*/
|
||||||
tls_handshake_t *handshake;
|
tls_handshake_t *handshake;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TLS alert handler
|
||||||
|
*/
|
||||||
|
tls_alert_t *alert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* State of alert handling
|
||||||
|
*/
|
||||||
|
alert_state_t state;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handshake input buffer
|
* Handshake input buffer
|
||||||
*/
|
*/
|
||||||
@@ -72,6 +94,23 @@ struct private_tls_fragmentation_t {
|
|||||||
*/
|
*/
|
||||||
#define MAX_TLS_HANDSHAKE_LEN 65536
|
#define MAX_TLS_HANDSHAKE_LEN 65536
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process a TLS alert
|
||||||
|
*/
|
||||||
|
static status_t process_alert(private_tls_fragmentation_t *this,
|
||||||
|
tls_reader_t *reader)
|
||||||
|
{
|
||||||
|
u_int8_t level, description;
|
||||||
|
|
||||||
|
if (!reader->read_uint8(reader, &level) ||
|
||||||
|
!reader->read_uint8(reader, &description))
|
||||||
|
{
|
||||||
|
this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
|
||||||
|
return NEED_MORE;
|
||||||
|
}
|
||||||
|
return this->alert->process(this->alert, level, description);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process TLS handshake protocol data
|
* Process TLS handshake protocol data
|
||||||
*/
|
*/
|
||||||
@@ -89,7 +128,8 @@ static status_t process_handshake(private_tls_fragmentation_t *this,
|
|||||||
if (reader->remaining(reader) > MAX_TLS_FRAGMENT_LEN)
|
if (reader->remaining(reader) > MAX_TLS_FRAGMENT_LEN)
|
||||||
{
|
{
|
||||||
DBG1(DBG_TLS, "TLS fragment has invalid length");
|
DBG1(DBG_TLS, "TLS fragment has invalid length");
|
||||||
return FAILED;
|
this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
|
||||||
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->input.len == 0)
|
if (this->input.len == 0)
|
||||||
@@ -97,13 +137,16 @@ static status_t process_handshake(private_tls_fragmentation_t *this,
|
|||||||
if (!reader->read_uint8(reader, &type) ||
|
if (!reader->read_uint8(reader, &type) ||
|
||||||
!reader->read_uint24(reader, &len))
|
!reader->read_uint24(reader, &len))
|
||||||
{
|
{
|
||||||
return FAILED;
|
DBG1(DBG_TLS, "TLS handshake header invalid");
|
||||||
|
this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
|
||||||
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
this->type = type;
|
this->type = type;
|
||||||
if (len > MAX_TLS_HANDSHAKE_LEN)
|
if (len > MAX_TLS_HANDSHAKE_LEN)
|
||||||
{
|
{
|
||||||
DBG1(DBG_TLS, "TLS handshake message exceeds maximum length");
|
DBG1(DBG_TLS, "TLS handshake message exceeds maximum length");
|
||||||
return FAILED;
|
this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
|
||||||
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
chunk_free(&this->input);
|
chunk_free(&this->input);
|
||||||
this->inpos = 0;
|
this->inpos = 0;
|
||||||
@@ -116,7 +159,9 @@ static status_t process_handshake(private_tls_fragmentation_t *this,
|
|||||||
len = min(this->input.len - this->inpos, reader->remaining(reader));
|
len = min(this->input.len - this->inpos, reader->remaining(reader));
|
||||||
if (!reader->read_data(reader, len, &data))
|
if (!reader->read_data(reader, len, &data))
|
||||||
{
|
{
|
||||||
return FAILED;
|
DBG1(DBG_TLS, "TLS fragment has invalid length");
|
||||||
|
this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
|
||||||
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
memcpy(this->input.ptr + this->inpos, data.ptr, len);
|
memcpy(this->input.ptr + this->inpos, data.ptr, len);
|
||||||
this->inpos += len;
|
this->inpos += len;
|
||||||
@@ -151,12 +196,14 @@ static status_t process_application(private_tls_fragmentation_t *this,
|
|||||||
if (reader->remaining(reader) > MAX_TLS_FRAGMENT_LEN)
|
if (reader->remaining(reader) > MAX_TLS_FRAGMENT_LEN)
|
||||||
{
|
{
|
||||||
DBG1(DBG_TLS, "TLS fragment has invalid length");
|
DBG1(DBG_TLS, "TLS fragment has invalid length");
|
||||||
return FAILED;
|
this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
|
||||||
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
status = this->application->process(this->application, reader);
|
status = this->application->process(this->application, reader);
|
||||||
if (status != NEED_MORE)
|
if (status != NEED_MORE)
|
||||||
{
|
{
|
||||||
return status;
|
this->alert->add(this->alert, TLS_FATAL, TLS_CLOSE_NOTIFY);
|
||||||
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NEED_MORE;
|
return NEED_MORE;
|
||||||
@@ -168,6 +215,15 @@ METHOD(tls_fragmentation_t, process, status_t,
|
|||||||
tls_reader_t *reader;
|
tls_reader_t *reader;
|
||||||
status_t status;
|
status_t status;
|
||||||
|
|
||||||
|
switch (this->state)
|
||||||
|
{
|
||||||
|
case ALERT_SENDING:
|
||||||
|
case ALERT_SENT:
|
||||||
|
/* don't accept more input, fatal error ocurred */
|
||||||
|
return NEED_MORE;
|
||||||
|
case ALERT_NONE:
|
||||||
|
break;
|
||||||
|
}
|
||||||
reader = tls_reader_create(data);
|
reader = tls_reader_create(data);
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
@@ -180,8 +236,7 @@ METHOD(tls_fragmentation_t, process, status_t,
|
|||||||
status = FAILED;
|
status = FAILED;
|
||||||
break;
|
break;
|
||||||
case TLS_ALERT:
|
case TLS_ALERT:
|
||||||
/* TODO: handle Alert */
|
status = process_alert(this, reader);
|
||||||
status = FAILED;
|
|
||||||
break;
|
break;
|
||||||
case TLS_HANDSHAKE:
|
case TLS_HANDSHAKE:
|
||||||
status = process_handshake(this, reader);
|
status = process_handshake(this, reader);
|
||||||
@@ -198,6 +253,29 @@ METHOD(tls_fragmentation_t, process, status_t,
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if alerts are pending
|
||||||
|
*/
|
||||||
|
static bool check_alerts(private_tls_fragmentation_t *this, chunk_t *data)
|
||||||
|
{
|
||||||
|
tls_alert_level_t level;
|
||||||
|
tls_alert_desc_t desc;
|
||||||
|
tls_writer_t *writer;
|
||||||
|
|
||||||
|
if (this->alert->get(this->alert, &level, &desc))
|
||||||
|
{
|
||||||
|
writer = tls_writer_create(2);
|
||||||
|
|
||||||
|
writer->write_uint8(writer, level);
|
||||||
|
writer->write_uint8(writer, desc);
|
||||||
|
|
||||||
|
*data = chunk_clone(writer->get_buf(writer));
|
||||||
|
writer->destroy(writer);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
METHOD(tls_fragmentation_t, build, status_t,
|
METHOD(tls_fragmentation_t, build, status_t,
|
||||||
private_tls_fragmentation_t *this, tls_content_type_t *type, chunk_t *data)
|
private_tls_fragmentation_t *this, tls_content_type_t *type, chunk_t *data)
|
||||||
{
|
{
|
||||||
@@ -206,6 +284,22 @@ METHOD(tls_fragmentation_t, build, status_t,
|
|||||||
tls_writer_t *writer, *msg;
|
tls_writer_t *writer, *msg;
|
||||||
status_t status = INVALID_STATE;
|
status_t status = INVALID_STATE;
|
||||||
|
|
||||||
|
switch (this->state)
|
||||||
|
{
|
||||||
|
case ALERT_SENDING:
|
||||||
|
this->state = ALERT_SENT;
|
||||||
|
return INVALID_STATE;
|
||||||
|
case ALERT_SENT:
|
||||||
|
return FAILED;
|
||||||
|
case ALERT_NONE:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (check_alerts(this, data))
|
||||||
|
{
|
||||||
|
this->state = ALERT_SENDING;
|
||||||
|
*type = TLS_ALERT;
|
||||||
|
return NEED_MORE;
|
||||||
|
}
|
||||||
if (this->handshake->cipherspec_changed(this->handshake))
|
if (this->handshake->cipherspec_changed(this->handshake))
|
||||||
{
|
{
|
||||||
*type = TLS_CHANGE_CIPHER_SPEC;
|
*type = TLS_CHANGE_CIPHER_SPEC;
|
||||||
@@ -227,6 +321,16 @@ METHOD(tls_fragmentation_t, build, status_t,
|
|||||||
*type = TLS_APPLICATION_DATA;
|
*type = TLS_APPLICATION_DATA;
|
||||||
this->output = chunk_clone(msg->get_buf(msg));
|
this->output = chunk_clone(msg->get_buf(msg));
|
||||||
}
|
}
|
||||||
|
else if (status != NEED_MORE)
|
||||||
|
{
|
||||||
|
this->alert->add(this->alert, TLS_FATAL, TLS_CLOSE_NOTIFY);
|
||||||
|
if (check_alerts(this, data))
|
||||||
|
{
|
||||||
|
this->state = ALERT_SENDING;
|
||||||
|
*type = TLS_ALERT;
|
||||||
|
return NEED_MORE;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -290,7 +394,7 @@ METHOD(tls_fragmentation_t, destroy, void,
|
|||||||
* See header
|
* See header
|
||||||
*/
|
*/
|
||||||
tls_fragmentation_t *tls_fragmentation_create(tls_handshake_t *handshake,
|
tls_fragmentation_t *tls_fragmentation_create(tls_handshake_t *handshake,
|
||||||
tls_application_t *application)
|
tls_alert_t *alert, tls_application_t *application)
|
||||||
{
|
{
|
||||||
private_tls_fragmentation_t *this;
|
private_tls_fragmentation_t *this;
|
||||||
|
|
||||||
@@ -301,6 +405,8 @@ tls_fragmentation_t *tls_fragmentation_create(tls_handshake_t *handshake,
|
|||||||
.destroy = _destroy,
|
.destroy = _destroy,
|
||||||
},
|
},
|
||||||
.handshake = handshake,
|
.handshake = handshake,
|
||||||
|
.alert = alert,
|
||||||
|
.state = ALERT_NONE,
|
||||||
.application = application,
|
.application = application,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -21,13 +21,13 @@
|
|||||||
#ifndef TLS_FRAGMENTATION_H_
|
#ifndef TLS_FRAGMENTATION_H_
|
||||||
#define TLS_FRAGMENTATION_H_
|
#define TLS_FRAGMENTATION_H_
|
||||||
|
|
||||||
typedef struct tls_fragmentation_t tls_fragmentation_t;
|
|
||||||
|
|
||||||
#include <library.h>
|
#include <library.h>
|
||||||
|
|
||||||
#include "tls.h"
|
#include "tls.h"
|
||||||
|
#include "tls_alert.h"
|
||||||
#include "tls_handshake.h"
|
#include "tls_handshake.h"
|
||||||
#include "tls_handshake.h"
|
|
||||||
|
typedef struct tls_fragmentation_t tls_fragmentation_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TLS record protocol fragmentation layer.
|
* TLS record protocol fragmentation layer.
|
||||||
@@ -71,10 +71,11 @@ struct tls_fragmentation_t {
|
|||||||
* Create a tls_fragmentation instance.
|
* Create a tls_fragmentation instance.
|
||||||
*
|
*
|
||||||
* @param handshake upper layer handshake protocol
|
* @param handshake upper layer handshake protocol
|
||||||
|
* @param alert TLS alert handler
|
||||||
* @param application upper layer application data or NULL
|
* @param application upper layer application data or NULL
|
||||||
* @return TLS fragmentation layer.
|
* @return TLS fragmentation layer
|
||||||
*/
|
*/
|
||||||
tls_fragmentation_t *tls_fragmentation_create(tls_handshake_t *handshake,
|
tls_fragmentation_t *tls_fragmentation_create(tls_handshake_t *handshake,
|
||||||
tls_application_t *application);
|
tls_alert_t *alert, tls_application_t *application);
|
||||||
|
|
||||||
#endif /** TLS_FRAGMENTATION_H_ @}*/
|
#endif /** TLS_FRAGMENTATION_H_ @}*/
|
||||||
|
|||||||
@@ -38,9 +38,10 @@ struct tls_handshake_t {
|
|||||||
* @param type TLS handshake message type
|
* @param type TLS handshake message type
|
||||||
* @param reader TLS data buffer
|
* @param reader TLS data buffer
|
||||||
* @return
|
* @return
|
||||||
* - SUCCESS if handshake complete
|
* - SUCCESS if TLS negotiation complete
|
||||||
* - FAILED if handshake failed
|
* - FAILED if a fatal TLS alert queued
|
||||||
* - NEED_MORE if another invocation of process/build needed
|
* - NEED_MORE if more invocations to process/build needed
|
||||||
|
* - DESTROY_ME if a fatal TLS alert received
|
||||||
*/
|
*/
|
||||||
status_t (*process)(tls_handshake_t *this,
|
status_t (*process)(tls_handshake_t *this,
|
||||||
tls_handshake_type_t type, tls_reader_t *reader);
|
tls_handshake_type_t type, tls_reader_t *reader);
|
||||||
|
|||||||
+47
-17
@@ -57,6 +57,11 @@ struct private_tls_peer_t {
|
|||||||
*/
|
*/
|
||||||
tls_crypto_t *crypto;
|
tls_crypto_t *crypto;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TLS alert handler
|
||||||
|
*/
|
||||||
|
tls_alert_t *alert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Peer identity
|
* Peer identity
|
||||||
*/
|
*/
|
||||||
@@ -125,7 +130,8 @@ static status_t process_server_hello(private_tls_peer_t *this,
|
|||||||
(reader->remaining(reader) && !reader->read_data16(reader, &ext)))
|
(reader->remaining(reader) && !reader->read_data16(reader, &ext)))
|
||||||
{
|
{
|
||||||
DBG1(DBG_TLS, "received invalid ServerHello");
|
DBG1(DBG_TLS, "received invalid ServerHello");
|
||||||
return FAILED;
|
this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
|
||||||
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(this->server_random, random.ptr, sizeof(this->server_random));
|
memcpy(this->server_random, random.ptr, sizeof(this->server_random));
|
||||||
@@ -134,14 +140,16 @@ static status_t process_server_hello(private_tls_peer_t *this,
|
|||||||
{
|
{
|
||||||
DBG1(DBG_TLS, "negotiated version %N not supported",
|
DBG1(DBG_TLS, "negotiated version %N not supported",
|
||||||
tls_version_names, version);
|
tls_version_names, version);
|
||||||
return FAILED;
|
this->alert->add(this->alert, TLS_FATAL, TLS_PROTOCOL_VERSION);
|
||||||
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
suite = cipher;
|
suite = cipher;
|
||||||
if (!this->crypto->select_cipher_suite(this->crypto, &suite, 1))
|
if (!this->crypto->select_cipher_suite(this->crypto, &suite, 1))
|
||||||
{
|
{
|
||||||
DBG1(DBG_TLS, "received TLS cipher suite %N inacceptable",
|
DBG1(DBG_TLS, "received TLS cipher suite %N inacceptable",
|
||||||
tls_cipher_suite_names, suite);
|
tls_cipher_suite_names, suite);
|
||||||
return FAILED;
|
this->alert->add(this->alert, TLS_FATAL, TLS_HANDSHAKE_FAILURE);
|
||||||
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
DBG1(DBG_TLS, "negotiated TLS version %N with suite %N",
|
DBG1(DBG_TLS, "negotiated TLS version %N with suite %N",
|
||||||
tls_version_names, version, tls_cipher_suite_names, suite);
|
tls_version_names, version, tls_cipher_suite_names, suite);
|
||||||
@@ -165,15 +173,19 @@ static status_t process_certificate(private_tls_peer_t *this,
|
|||||||
|
|
||||||
if (!reader->read_data24(reader, &data))
|
if (!reader->read_data24(reader, &data))
|
||||||
{
|
{
|
||||||
return FAILED;
|
DBG1(DBG_TLS, "certificate message header invalid");
|
||||||
|
this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
|
||||||
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
certs = tls_reader_create(data);
|
certs = tls_reader_create(data);
|
||||||
while (certs->remaining(certs))
|
while (certs->remaining(certs))
|
||||||
{
|
{
|
||||||
if (!certs->read_data24(certs, &data))
|
if (!certs->read_data24(certs, &data))
|
||||||
{
|
{
|
||||||
|
DBG1(DBG_TLS, "certificate message invalid");
|
||||||
|
this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
|
||||||
certs->destroy(certs);
|
certs->destroy(certs);
|
||||||
return FAILED;
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
|
cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
|
||||||
BUILD_BLOB_ASN1_DER, data, BUILD_END);
|
BUILD_BLOB_ASN1_DER, data, BUILD_END);
|
||||||
@@ -198,6 +210,7 @@ static status_t process_certificate(private_tls_peer_t *this,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
DBG1(DBG_TLS, "parsing TLS certificate failed, skipped");
|
DBG1(DBG_TLS, "parsing TLS certificate failed, skipped");
|
||||||
|
this->alert->add(this->alert, TLS_WARNING, TLS_BAD_CERTIFICATE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
certs->destroy(certs);
|
certs->destroy(certs);
|
||||||
@@ -220,27 +233,35 @@ static status_t process_certreq(private_tls_peer_t *this, tls_reader_t *reader)
|
|||||||
|
|
||||||
if (!reader->read_data8(reader, &types))
|
if (!reader->read_data8(reader, &types))
|
||||||
{
|
{
|
||||||
return FAILED;
|
DBG1(DBG_TLS, "certreq message header invalid");
|
||||||
|
this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
|
||||||
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
if (this->tls->get_version(this->tls) >= TLS_1_2)
|
if (this->tls->get_version(this->tls) >= TLS_1_2)
|
||||||
{
|
{
|
||||||
if (!reader->read_data16(reader, &hashsig))
|
if (!reader->read_data16(reader, &hashsig))
|
||||||
{
|
{
|
||||||
return FAILED;
|
DBG1(DBG_TLS, "certreq message invalid");
|
||||||
|
this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
|
||||||
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
/* TODO: store supported hashsig algorithms */
|
/* TODO: store supported hashsig algorithms */
|
||||||
}
|
}
|
||||||
if (!reader->read_data16(reader, &data))
|
if (!reader->read_data16(reader, &data))
|
||||||
{
|
{
|
||||||
return FAILED;
|
DBG1(DBG_TLS, "certreq message invalid");
|
||||||
|
this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
|
||||||
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
authorities = tls_reader_create(data);
|
authorities = tls_reader_create(data);
|
||||||
while (authorities->remaining(authorities))
|
while (authorities->remaining(authorities))
|
||||||
{
|
{
|
||||||
if (!authorities->read_data16(authorities, &data))
|
if (!authorities->read_data16(authorities, &data))
|
||||||
{
|
{
|
||||||
|
DBG1(DBG_TLS, "certreq message invalid");
|
||||||
|
this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
|
||||||
authorities->destroy(authorities);
|
authorities->destroy(authorities);
|
||||||
return FAILED;
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
id = identification_create_from_encoding(ID_DER_ASN1_DN, data);
|
id = identification_create_from_encoding(ID_DER_ASN1_DN, data);
|
||||||
cert = lib->credmgr->get_cert(lib->credmgr,
|
cert = lib->credmgr->get_cert(lib->credmgr,
|
||||||
@@ -284,17 +305,20 @@ static status_t process_finished(private_tls_peer_t *this, tls_reader_t *reader)
|
|||||||
if (!reader->read_data(reader, sizeof(buf), &received))
|
if (!reader->read_data(reader, sizeof(buf), &received))
|
||||||
{
|
{
|
||||||
DBG1(DBG_TLS, "received server finished too short");
|
DBG1(DBG_TLS, "received server finished too short");
|
||||||
return FAILED;
|
this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
|
||||||
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
if (!this->crypto->calculate_finished(this->crypto, "server finished", buf))
|
if (!this->crypto->calculate_finished(this->crypto, "server finished", buf))
|
||||||
{
|
{
|
||||||
DBG1(DBG_TLS, "calculating server finished failed");
|
DBG1(DBG_TLS, "calculating server finished failed");
|
||||||
return FAILED;
|
this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
|
||||||
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
if (!chunk_equals(received, chunk_from_thing(buf)))
|
if (!chunk_equals(received, chunk_from_thing(buf)))
|
||||||
{
|
{
|
||||||
DBG1(DBG_TLS, "received server finished invalid");
|
DBG1(DBG_TLS, "received server finished invalid");
|
||||||
return FAILED;
|
this->alert->add(this->alert, TLS_FATAL, TLS_DECRYPT_ERROR);
|
||||||
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
this->state = STATE_COMPLETE;
|
this->state = STATE_COMPLETE;
|
||||||
this->crypto->derive_eap_msk(this->crypto,
|
this->crypto->derive_eap_msk(this->crypto,
|
||||||
@@ -348,11 +372,13 @@ METHOD(tls_handshake_t, process, status_t,
|
|||||||
default:
|
default:
|
||||||
DBG1(DBG_TLS, "TLS %N not expected in current state",
|
DBG1(DBG_TLS, "TLS %N not expected in current state",
|
||||||
tls_handshake_type_names, type);
|
tls_handshake_type_names, type);
|
||||||
return FAILED;
|
this->alert->add(this->alert, TLS_FATAL, TLS_UNEXPECTED_MESSAGE);
|
||||||
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
DBG1(DBG_TLS, "TLS %N expected, but received %N",
|
DBG1(DBG_TLS, "TLS %N expected, but received %N",
|
||||||
tls_handshake_type_names, expected, tls_handshake_type_names, type);
|
tls_handshake_type_names, expected, tls_handshake_type_names, type);
|
||||||
return FAILED;
|
this->alert->add(this->alert, TLS_FATAL, TLS_UNEXPECTED_MESSAGE);
|
||||||
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -370,7 +396,9 @@ static status_t send_client_hello(private_tls_peer_t *this,
|
|||||||
rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
|
rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
|
||||||
if (!rng)
|
if (!rng)
|
||||||
{
|
{
|
||||||
return FAILED;
|
DBG1(DBG_TLS, "no suitable RNG found to generate client random");
|
||||||
|
this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
|
||||||
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
rng->get_bytes(rng, sizeof(this->client_random) - 4, this->client_random + 4);
|
rng->get_bytes(rng, sizeof(this->client_random) - 4, this->client_random + 4);
|
||||||
rng->destroy(rng);
|
rng->destroy(rng);
|
||||||
@@ -420,7 +448,8 @@ static status_t send_certificate(private_tls_peer_t *this,
|
|||||||
if (!this->private)
|
if (!this->private)
|
||||||
{
|
{
|
||||||
DBG1(DBG_TLS, "no TLS peer certificate found for '%Y'", this->peer);
|
DBG1(DBG_TLS, "no TLS peer certificate found for '%Y'", this->peer);
|
||||||
return FAILED;
|
this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
|
||||||
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* generate certificate payload */
|
/* generate certificate payload */
|
||||||
@@ -640,7 +669,7 @@ METHOD(tls_handshake_t, destroy, void,
|
|||||||
/**
|
/**
|
||||||
* See header
|
* See header
|
||||||
*/
|
*/
|
||||||
tls_peer_t *tls_peer_create(tls_t *tls, tls_crypto_t *crypto,
|
tls_peer_t *tls_peer_create(tls_t *tls, tls_crypto_t *crypto, tls_alert_t *alert,
|
||||||
identification_t *peer, identification_t *server)
|
identification_t *peer, identification_t *server)
|
||||||
{
|
{
|
||||||
private_tls_peer_t *this;
|
private_tls_peer_t *this;
|
||||||
@@ -659,6 +688,7 @@ tls_peer_t *tls_peer_create(tls_t *tls, tls_crypto_t *crypto,
|
|||||||
.state = STATE_INIT,
|
.state = STATE_INIT,
|
||||||
.tls = tls,
|
.tls = tls,
|
||||||
.crypto = crypto,
|
.crypto = crypto,
|
||||||
|
.alert = alert,
|
||||||
.peer = peer,
|
.peer = peer,
|
||||||
.server = server,
|
.server = server,
|
||||||
.peer_auth = auth_cfg_create(),
|
.peer_auth = auth_cfg_create(),
|
||||||
|
|||||||
@@ -41,8 +41,14 @@ struct tls_peer_t {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a tls_peer instance.
|
* Create a tls_peer instance.
|
||||||
|
*
|
||||||
|
* @param tls TLS stack
|
||||||
|
* @param crypto TLS crypto helper
|
||||||
|
* @param alert TLS alert handler
|
||||||
|
* @param peer peer identity
|
||||||
|
* @param server server identity
|
||||||
*/
|
*/
|
||||||
tls_peer_t *tls_peer_create(tls_t *tls, tls_crypto_t *crypto,
|
tls_peer_t *tls_peer_create(tls_t *tls, tls_crypto_t *crypto, tls_alert_t *alert,
|
||||||
identification_t *peer, identification_t *server);
|
identification_t *peer, identification_t *server);
|
||||||
|
|
||||||
#endif /** TLS_PEER_H_ @}*/
|
#endif /** TLS_PEER_H_ @}*/
|
||||||
|
|||||||
+34
-14
@@ -30,15 +30,20 @@ struct private_tls_protection_t {
|
|||||||
tls_protection_t public;
|
tls_protection_t public;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TLS context
|
* negotiated TLS version
|
||||||
*/
|
*/
|
||||||
tls_t *tls;
|
tls_version_t version;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Upper layer, TLS record compression
|
* Upper layer, TLS record compression
|
||||||
*/
|
*/
|
||||||
tls_compression_t *compression;
|
tls_compression_t *compression;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TLS alert handler
|
||||||
|
*/
|
||||||
|
tls_alert_t *alert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RNG if we generate IVs ourself
|
* RNG if we generate IVs ourself
|
||||||
*/
|
*/
|
||||||
@@ -106,6 +111,11 @@ static chunk_t sigheader(u_int32_t seq, u_int8_t type,
|
|||||||
METHOD(tls_protection_t, process, status_t,
|
METHOD(tls_protection_t, process, status_t,
|
||||||
private_tls_protection_t *this, tls_content_type_t type, chunk_t data)
|
private_tls_protection_t *this, tls_content_type_t type, chunk_t data)
|
||||||
{
|
{
|
||||||
|
if (this->alert->fatal(this->alert))
|
||||||
|
{ /* don't accept more input, fatal error ocurred */
|
||||||
|
return NEED_MORE;
|
||||||
|
}
|
||||||
|
|
||||||
if (this->crypter_in)
|
if (this->crypter_in)
|
||||||
{
|
{
|
||||||
chunk_t iv, next_iv = chunk_empty;
|
chunk_t iv, next_iv = chunk_empty;
|
||||||
@@ -117,7 +127,8 @@ METHOD(tls_protection_t, process, status_t,
|
|||||||
if (data.len < bs || data.len % bs)
|
if (data.len < bs || data.len % bs)
|
||||||
{
|
{
|
||||||
DBG1(DBG_TLS, "encrypted TLS record length invalid");
|
DBG1(DBG_TLS, "encrypted TLS record length invalid");
|
||||||
return FAILED;
|
this->alert->add(this->alert, TLS_FATAL, TLS_BAD_RECORD_MAC);
|
||||||
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
iv = this->iv_in;
|
iv = this->iv_in;
|
||||||
next_iv = chunk_clone(chunk_create(data.ptr + data.len - bs, bs));
|
next_iv = chunk_clone(chunk_create(data.ptr + data.len - bs, bs));
|
||||||
@@ -130,7 +141,8 @@ METHOD(tls_protection_t, process, status_t,
|
|||||||
if (data.len < bs || data.len % bs)
|
if (data.len < bs || data.len % bs)
|
||||||
{
|
{
|
||||||
DBG1(DBG_TLS, "encrypted TLS record length invalid");
|
DBG1(DBG_TLS, "encrypted TLS record length invalid");
|
||||||
return FAILED;
|
this->alert->add(this->alert, TLS_FATAL, TLS_BAD_RECORD_MAC);
|
||||||
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this->crypter_in->decrypt(this->crypter_in, data, iv, NULL);
|
this->crypter_in->decrypt(this->crypter_in, data, iv, NULL);
|
||||||
@@ -145,7 +157,8 @@ METHOD(tls_protection_t, process, status_t,
|
|||||||
if (padding_length >= data.len)
|
if (padding_length >= data.len)
|
||||||
{
|
{
|
||||||
DBG1(DBG_TLS, "invalid TLS record padding");
|
DBG1(DBG_TLS, "invalid TLS record padding");
|
||||||
return FAILED;
|
this->alert->add(this->alert, TLS_FATAL, TLS_BAD_RECORD_MAC);
|
||||||
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
data.len -= padding_length + 1;
|
data.len -= padding_length + 1;
|
||||||
}
|
}
|
||||||
@@ -158,19 +171,20 @@ METHOD(tls_protection_t, process, status_t,
|
|||||||
if (data.len <= bs)
|
if (data.len <= bs)
|
||||||
{
|
{
|
||||||
DBG1(DBG_TLS, "TLS record too short to verify MAC");
|
DBG1(DBG_TLS, "TLS record too short to verify MAC");
|
||||||
return FAILED;
|
this->alert->add(this->alert, TLS_FATAL, TLS_BAD_RECORD_MAC);
|
||||||
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
mac = chunk_skip(data, data.len - bs);
|
mac = chunk_skip(data, data.len - bs);
|
||||||
data.len -= bs;
|
data.len -= bs;
|
||||||
|
|
||||||
header = sigheader(this->seq_in, type,
|
header = sigheader(this->seq_in, type, this->version, data.len);
|
||||||
this->tls->get_version(this->tls), data.len);
|
|
||||||
macdata = chunk_cat("mc", header, data);
|
macdata = chunk_cat("mc", header, data);
|
||||||
if (!this->signer_in->verify_signature(this->signer_in, macdata, mac))
|
if (!this->signer_in->verify_signature(this->signer_in, macdata, mac))
|
||||||
{
|
{
|
||||||
DBG1(DBG_TLS, "TLS record MAC verification failed");
|
DBG1(DBG_TLS, "TLS record MAC verification failed");
|
||||||
free(macdata.ptr);
|
free(macdata.ptr);
|
||||||
return FAILED;
|
this->alert->add(this->alert, TLS_FATAL, TLS_BAD_RECORD_MAC);
|
||||||
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
free(macdata.ptr);
|
free(macdata.ptr);
|
||||||
}
|
}
|
||||||
@@ -204,8 +218,7 @@ METHOD(tls_protection_t, build, status_t,
|
|||||||
{
|
{
|
||||||
chunk_t mac, header;
|
chunk_t mac, header;
|
||||||
|
|
||||||
header = sigheader(this->seq_out, *type,
|
header = sigheader(this->seq_out, *type, this->version, data->len);
|
||||||
this->tls->get_version(this->tls), data->len);
|
|
||||||
this->signer_out->get_signature(this->signer_out, header, NULL);
|
this->signer_out->get_signature(this->signer_out, header, NULL);
|
||||||
free(header.ptr);
|
free(header.ptr);
|
||||||
this->signer_out->allocate_signature(this->signer_out, *data, &mac);
|
this->signer_out->allocate_signature(this->signer_out, *data, &mac);
|
||||||
@@ -283,6 +296,12 @@ METHOD(tls_protection_t, set_cipher, void,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
METHOD(tls_protection_t, set_version, void,
|
||||||
|
private_tls_protection_t *this, tls_version_t version)
|
||||||
|
{
|
||||||
|
this->version = version;
|
||||||
|
}
|
||||||
|
|
||||||
METHOD(tls_protection_t, destroy, void,
|
METHOD(tls_protection_t, destroy, void,
|
||||||
private_tls_protection_t *this)
|
private_tls_protection_t *this)
|
||||||
{
|
{
|
||||||
@@ -293,8 +312,8 @@ METHOD(tls_protection_t, destroy, void,
|
|||||||
/**
|
/**
|
||||||
* See header
|
* See header
|
||||||
*/
|
*/
|
||||||
tls_protection_t *tls_protection_create(tls_t *tls,
|
tls_protection_t *tls_protection_create(tls_compression_t *compression,
|
||||||
tls_compression_t *compression)
|
tls_alert_t *alert)
|
||||||
{
|
{
|
||||||
private_tls_protection_t *this;
|
private_tls_protection_t *this;
|
||||||
|
|
||||||
@@ -303,9 +322,10 @@ tls_protection_t *tls_protection_create(tls_t *tls,
|
|||||||
.process = _process,
|
.process = _process,
|
||||||
.build = _build,
|
.build = _build,
|
||||||
.set_cipher = _set_cipher,
|
.set_cipher = _set_cipher,
|
||||||
|
.set_version = _set_version,
|
||||||
.destroy = _destroy,
|
.destroy = _destroy,
|
||||||
},
|
},
|
||||||
.tls = tls,
|
.alert = alert,
|
||||||
.compression = compression,
|
.compression = compression,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -21,13 +21,14 @@
|
|||||||
#ifndef TLS_PROTECTION_H_
|
#ifndef TLS_PROTECTION_H_
|
||||||
#define TLS_PROTECTION_H_
|
#define TLS_PROTECTION_H_
|
||||||
|
|
||||||
typedef struct tls_protection_t tls_protection_t;
|
|
||||||
|
|
||||||
#include <library.h>
|
#include <library.h>
|
||||||
|
|
||||||
#include "tls.h"
|
#include "tls.h"
|
||||||
|
#include "tls_alert.h"
|
||||||
#include "tls_compression.h"
|
#include "tls_compression.h"
|
||||||
|
|
||||||
|
typedef struct tls_protection_t tls_protection_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TLS record protocol protection layer.
|
* TLS record protocol protection layer.
|
||||||
*/
|
*/
|
||||||
@@ -71,6 +72,13 @@ struct tls_protection_t {
|
|||||||
void (*set_cipher)(tls_protection_t *this, bool inbound, signer_t *signer,
|
void (*set_cipher)(tls_protection_t *this, bool inbound, signer_t *signer,
|
||||||
crypter_t *crypter, chunk_t iv);
|
crypter_t *crypter, chunk_t iv);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the TLS version negotiated, used for MAC calculation.
|
||||||
|
*
|
||||||
|
* @param version TLS version negotiated
|
||||||
|
*/
|
||||||
|
void (*set_version)(tls_protection_t *this, tls_version_t version);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroy a tls_protection_t.
|
* Destroy a tls_protection_t.
|
||||||
*/
|
*/
|
||||||
@@ -80,11 +88,11 @@ struct tls_protection_t {
|
|||||||
/**
|
/**
|
||||||
* Create a tls_protection instance.
|
* Create a tls_protection instance.
|
||||||
*
|
*
|
||||||
* @param tls TLS context
|
|
||||||
* @param compression compression layer of TLS stack
|
* @param compression compression layer of TLS stack
|
||||||
|
* @param alert TLS alert handler
|
||||||
* @return TLS protection layer.
|
* @return TLS protection layer.
|
||||||
*/
|
*/
|
||||||
tls_protection_t *tls_protection_create(tls_t *tls,
|
tls_protection_t *tls_protection_create(tls_compression_t *compression,
|
||||||
tls_compression_t *compression);
|
tls_alert_t *alert);
|
||||||
|
|
||||||
#endif /** TLS_PROTECTION_H_ @}*/
|
#endif /** TLS_PROTECTION_H_ @}*/
|
||||||
|
|||||||
+39
-15
@@ -59,6 +59,11 @@ struct private_tls_server_t {
|
|||||||
*/
|
*/
|
||||||
tls_crypto_t *crypto;
|
tls_crypto_t *crypto;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TLS alert handler
|
||||||
|
*/
|
||||||
|
tls_alert_t *alert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Server identity
|
* Server identity
|
||||||
*/
|
*/
|
||||||
@@ -132,7 +137,8 @@ static status_t process_client_hello(private_tls_server_t *this,
|
|||||||
(reader->remaining(reader) && !reader->read_data16(reader, &ext)))
|
(reader->remaining(reader) && !reader->read_data16(reader, &ext)))
|
||||||
{
|
{
|
||||||
DBG1(DBG_TLS, "received invalid ClientHello");
|
DBG1(DBG_TLS, "received invalid ClientHello");
|
||||||
return FAILED;
|
this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
|
||||||
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(this->client_random, random.ptr, sizeof(this->client_random));
|
memcpy(this->client_random, random.ptr, sizeof(this->client_random));
|
||||||
@@ -141,7 +147,8 @@ static status_t process_client_hello(private_tls_server_t *this,
|
|||||||
{
|
{
|
||||||
DBG1(DBG_TLS, "negotiated version %N not supported",
|
DBG1(DBG_TLS, "negotiated version %N not supported",
|
||||||
tls_version_names, version);
|
tls_version_names, version);
|
||||||
return FAILED;
|
this->alert->add(this->alert, TLS_FATAL, TLS_PROTOCOL_VERSION);
|
||||||
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
count = ciphers.len / sizeof(u_int16_t);
|
count = ciphers.len / sizeof(u_int16_t);
|
||||||
suites = alloca(count * sizeof(tls_cipher_suite_t));
|
suites = alloca(count * sizeof(tls_cipher_suite_t));
|
||||||
@@ -155,7 +162,8 @@ static status_t process_client_hello(private_tls_server_t *this,
|
|||||||
if (!this->suite)
|
if (!this->suite)
|
||||||
{
|
{
|
||||||
DBG1(DBG_TLS, "received cipher suites inacceptable");
|
DBG1(DBG_TLS, "received cipher suites inacceptable");
|
||||||
return FAILED;
|
this->alert->add(this->alert, TLS_FATAL, TLS_HANDSHAKE_FAILURE);
|
||||||
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
DBG1(DBG_TLS, "negotiated TLS version %N with suite %N",
|
DBG1(DBG_TLS, "negotiated TLS version %N with suite %N",
|
||||||
tls_version_names, version, tls_cipher_suite_names, this->suite);
|
tls_version_names, version, tls_cipher_suite_names, this->suite);
|
||||||
@@ -179,15 +187,19 @@ static status_t process_certificate(private_tls_server_t *this,
|
|||||||
|
|
||||||
if (!reader->read_data24(reader, &data))
|
if (!reader->read_data24(reader, &data))
|
||||||
{
|
{
|
||||||
return FAILED;
|
DBG1(DBG_TLS, "certificate message header invalid");
|
||||||
|
this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
|
||||||
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
certs = tls_reader_create(data);
|
certs = tls_reader_create(data);
|
||||||
while (certs->remaining(certs))
|
while (certs->remaining(certs))
|
||||||
{
|
{
|
||||||
if (!certs->read_data24(certs, &data))
|
if (!certs->read_data24(certs, &data))
|
||||||
{
|
{
|
||||||
|
DBG1(DBG_TLS, "certificate message invalid");
|
||||||
|
this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
|
||||||
certs->destroy(certs);
|
certs->destroy(certs);
|
||||||
return FAILED;
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
|
cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
|
||||||
BUILD_BLOB_ASN1_DER, data, BUILD_END);
|
BUILD_BLOB_ASN1_DER, data, BUILD_END);
|
||||||
@@ -211,6 +223,7 @@ static status_t process_certificate(private_tls_server_t *this,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
DBG1(DBG_TLS, "parsing TLS certificate failed, skipped");
|
DBG1(DBG_TLS, "parsing TLS certificate failed, skipped");
|
||||||
|
this->alert->add(this->alert, TLS_WARNING, TLS_BAD_CERTIFICATE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
certs->destroy(certs);
|
certs->destroy(certs);
|
||||||
@@ -232,7 +245,8 @@ static status_t process_key_exchange(private_tls_server_t *this,
|
|||||||
if (!reader->read_data16(reader, &encrypted))
|
if (!reader->read_data16(reader, &encrypted))
|
||||||
{
|
{
|
||||||
DBG1(DBG_TLS, "received invalid Client Key Exchange");
|
DBG1(DBG_TLS, "received invalid Client Key Exchange");
|
||||||
return FAILED;
|
this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
|
||||||
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this->private ||
|
if (!this->private ||
|
||||||
@@ -240,7 +254,8 @@ static status_t process_key_exchange(private_tls_server_t *this,
|
|||||||
encrypted, &premaster))
|
encrypted, &premaster))
|
||||||
{
|
{
|
||||||
DBG1(DBG_TLS, "decrypting Client Key Exchange data failed");
|
DBG1(DBG_TLS, "decrypting Client Key Exchange data failed");
|
||||||
return FAILED;
|
this->alert->add(this->alert, TLS_FATAL, TLS_DECRYPT_ERROR);
|
||||||
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
this->crypto->derive_secrets(this->crypto, premaster,
|
this->crypto->derive_secrets(this->crypto, premaster,
|
||||||
chunk_from_thing(this->client_random),
|
chunk_from_thing(this->client_random),
|
||||||
@@ -282,7 +297,8 @@ static status_t process_cert_verify(private_tls_server_t *this,
|
|||||||
{
|
{
|
||||||
DBG1(DBG_TLS, "no trusted certificate found for '%Y' to verify TLS peer",
|
DBG1(DBG_TLS, "no trusted certificate found for '%Y' to verify TLS peer",
|
||||||
this->peer);
|
this->peer);
|
||||||
return FAILED;
|
this->alert->add(this->alert, TLS_FATAL, TLS_CERTIFICATE_UNKNOWN);
|
||||||
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->crypto->append_handshake(this->crypto,
|
this->crypto->append_handshake(this->crypto,
|
||||||
@@ -303,17 +319,20 @@ static status_t process_finished(private_tls_server_t *this,
|
|||||||
if (!reader->read_data(reader, sizeof(buf), &received))
|
if (!reader->read_data(reader, sizeof(buf), &received))
|
||||||
{
|
{
|
||||||
DBG1(DBG_TLS, "received client finished too short");
|
DBG1(DBG_TLS, "received client finished too short");
|
||||||
return FAILED;
|
this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
|
||||||
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
if (!this->crypto->calculate_finished(this->crypto, "client finished", buf))
|
if (!this->crypto->calculate_finished(this->crypto, "client finished", buf))
|
||||||
{
|
{
|
||||||
DBG1(DBG_TLS, "calculating client finished failed");
|
DBG1(DBG_TLS, "calculating client finished failed");
|
||||||
return FAILED;
|
this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
|
||||||
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
if (!chunk_equals(received, chunk_from_thing(buf)))
|
if (!chunk_equals(received, chunk_from_thing(buf)))
|
||||||
{
|
{
|
||||||
DBG1(DBG_TLS, "received client finished invalid");
|
DBG1(DBG_TLS, "received client finished invalid");
|
||||||
return FAILED;
|
this->alert->add(this->alert, TLS_FATAL, TLS_DECRYPT_ERROR);
|
||||||
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->crypto->append_handshake(this->crypto, TLS_FINISHED, received);
|
this->crypto->append_handshake(this->crypto, TLS_FINISHED, received);
|
||||||
@@ -377,11 +396,13 @@ METHOD(tls_handshake_t, process, status_t,
|
|||||||
default:
|
default:
|
||||||
DBG1(DBG_TLS, "TLS %N not expected in current state",
|
DBG1(DBG_TLS, "TLS %N not expected in current state",
|
||||||
tls_handshake_type_names, type);
|
tls_handshake_type_names, type);
|
||||||
return FAILED;
|
this->alert->add(this->alert, TLS_FATAL, TLS_UNEXPECTED_MESSAGE);
|
||||||
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
DBG1(DBG_TLS, "TLS %N expected, but received %N",
|
DBG1(DBG_TLS, "TLS %N expected, but received %N",
|
||||||
tls_handshake_type_names, expected, tls_handshake_type_names, type);
|
tls_handshake_type_names, expected, tls_handshake_type_names, type);
|
||||||
return FAILED;
|
this->alert->add(this->alert, TLS_FATAL, TLS_UNEXPECTED_MESSAGE);
|
||||||
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -397,6 +418,7 @@ static status_t send_server_hello(private_tls_server_t *this,
|
|||||||
rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
|
rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
|
||||||
if (!rng)
|
if (!rng)
|
||||||
{
|
{
|
||||||
|
DBG1(DBG_TLS, "no suitable RNG found to generate server random");
|
||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
rng->get_bytes(rng, sizeof(this->server_random) - 4, this->server_random + 4);
|
rng->get_bytes(rng, sizeof(this->server_random) - 4, this->server_random + 4);
|
||||||
@@ -630,8 +652,9 @@ METHOD(tls_handshake_t, destroy, void,
|
|||||||
/**
|
/**
|
||||||
* See header
|
* See header
|
||||||
*/
|
*/
|
||||||
tls_server_t *tls_server_create(tls_t *tls, tls_crypto_t *crypto,
|
tls_server_t *tls_server_create(tls_t *tls,
|
||||||
identification_t *server, identification_t *peer)
|
tls_crypto_t *crypto, tls_alert_t *alert,
|
||||||
|
identification_t *server, identification_t *peer)
|
||||||
{
|
{
|
||||||
private_tls_server_t *this;
|
private_tls_server_t *this;
|
||||||
|
|
||||||
@@ -648,6 +671,7 @@ tls_server_t *tls_server_create(tls_t *tls, tls_crypto_t *crypto,
|
|||||||
},
|
},
|
||||||
.tls = tls,
|
.tls = tls,
|
||||||
.crypto = crypto,
|
.crypto = crypto,
|
||||||
|
.alert = alert,
|
||||||
.server = server,
|
.server = server,
|
||||||
.peer = peer,
|
.peer = peer,
|
||||||
.state = STATE_INIT,
|
.state = STATE_INIT,
|
||||||
|
|||||||
@@ -41,8 +41,15 @@ struct tls_server_t {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a tls_server instance.
|
* Create a tls_server instance.
|
||||||
|
*
|
||||||
|
* @param tls TLS stack
|
||||||
|
* @param crypto TLS crypto helper
|
||||||
|
* @param alert TLS alert handler
|
||||||
|
* @param server server identity
|
||||||
|
* @param peer peer identity
|
||||||
*/
|
*/
|
||||||
tls_server_t *tls_server_create(tls_t *tls, tls_crypto_t *crypto,
|
tls_server_t *tls_server_create(tls_t *tls,
|
||||||
identification_t *server, identification_t *peer);
|
tls_crypto_t *crypto, tls_alert_t *alert,
|
||||||
|
identification_t *server, identification_t *peer);
|
||||||
|
|
||||||
#endif /** TLS_SERVER_H_ @}*/
|
#endif /** TLS_SERVER_H_ @}*/
|
||||||
|
|||||||
Reference in New Issue
Block a user