Add CRC32 checksums to all message
Calculate CRC32 checksum of the whole ZRTP packet and add it at the end of packet and verify the checksum when a packet is received. If the verification fails, the packet is simply discarded
This commit is contained in:
parent
f62784cf27
commit
ca669fc1b5
|
@ -217,3 +217,24 @@ void kvz_rtp::crypto::random::generate_random(uint8_t *out, size_t len)
|
|||
/* do not block ever */
|
||||
CryptoPP::OS_GenerateRandomBlock(false, out, len);
|
||||
}
|
||||
|
||||
/* ***************** crc32 ***************** */
|
||||
|
||||
void kvz_rtp::crypto::crc32::get_crc32(uint8_t *input, size_t len, uint32_t *output)
|
||||
{
|
||||
CryptoPP::CRC32 crc32;
|
||||
|
||||
crc32.Update(input, len);
|
||||
crc32.TruncatedFinal((uint8_t *)output, sizeof(uint32_t));
|
||||
}
|
||||
|
||||
bool kvz_rtp::crypto::crc32::verify_crc32(uint8_t *input, size_t len, uint32_t old_crc)
|
||||
{
|
||||
CryptoPP::CRC32 crc32;
|
||||
uint32_t new_crc;
|
||||
|
||||
crc32.Update(input, len);
|
||||
crc32.TruncatedFinal((uint8_t *)&new_crc, sizeof(uint32_t));
|
||||
|
||||
return new_crc == old_crc;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "crypto/3rdparty/cryptopp/modes.h"
|
||||
#include "crypto/3rdparty/cryptopp/osrng.h"
|
||||
#include "crypto/3rdparty/cryptopp/sha.h"
|
||||
#include "crypto/3rdparty/cryptopp/crc.h"
|
||||
|
||||
namespace kvz_rtp {
|
||||
|
||||
|
@ -120,5 +121,10 @@ namespace kvz_rtp {
|
|||
namespace random {
|
||||
void generate_random(uint8_t *out, size_t len);
|
||||
};
|
||||
|
||||
namespace crc32 {
|
||||
void get_crc32(uint8_t *input, size_t len, uint32_t *output);
|
||||
bool verify_crc32(uint8_t *input, size_t len, uint32_t old_crc);
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
kvz_rtp::zrtp_msg::commit::commit(zrtp_session_t& session)
|
||||
{
|
||||
/* temporary storage for the full hmac hash */
|
||||
uint8_t mac_full[32];
|
||||
uint8_t mac_full[32] = { 0 };
|
||||
|
||||
LOG_DEBUG("Create ZRTP Commit message!");
|
||||
|
||||
|
@ -44,13 +44,17 @@ kvz_rtp::zrtp_msg::commit::commit(zrtp_session_t& session)
|
|||
msg->auth_tag_type = session.auth_tag_type;
|
||||
msg->key_agreement_type = session.key_agreement_type;
|
||||
|
||||
/* Calculate truncated HMAC-SHA256 for the Commit Message */
|
||||
auto hmac_sha256 = kvz_rtp::crypto::hmac::sha256(session.hashes[1], 32);
|
||||
|
||||
hmac_sha256.update((uint8_t *)frame_, len_ - 8);
|
||||
hmac_sha256.update((uint8_t *)frame_, len_ - 8 - 4);
|
||||
hmac_sha256.final(mac_full);
|
||||
|
||||
memcpy(&msg->mac, mac_full, sizeof(uint64_t));
|
||||
|
||||
/* Calculate CRC32 for the whole ZRTP packet */
|
||||
kvz_rtp::crypto::crc32::get_crc32((uint8_t *)frame_, len_ - 4, &msg->crc);
|
||||
|
||||
/* Finally make a copy of the message and save it for later use */
|
||||
session.l_msg.commit.first = len_;
|
||||
session.l_msg.commit.second = (kvz_rtp::zrtp_msg::zrtp_commit *)new uint8_t[len_];
|
||||
|
|
|
@ -26,6 +26,7 @@ namespace kvz_rtp {
|
|||
|
||||
uint32_t hvi[8];
|
||||
uint32_t mac[2];
|
||||
uint32_t crc;
|
||||
};
|
||||
|
||||
class commit {
|
||||
|
|
|
@ -35,6 +35,9 @@ kvz_rtp::zrtp_msg::confack::confack(zrtp_session_t& session)
|
|||
msg->msg_start.length = len_ - sizeof(zrtp_header);
|
||||
|
||||
memcpy(&msg->msg_start.msgblock, ZRTP_CONFACK, 8);
|
||||
|
||||
/* Calculate CRC32 for the whole ZRTP packet */
|
||||
kvz_rtp::crypto::crc32::get_crc32((uint8_t *)frame_, len_ - 4, &msg->crc);
|
||||
}
|
||||
|
||||
kvz_rtp::zrtp_msg::confack::~confack()
|
||||
|
|
|
@ -12,6 +12,7 @@ namespace kvz_rtp {
|
|||
|
||||
struct zrtp_confack {
|
||||
zrtp_msg msg_start;
|
||||
uint32_t crc;
|
||||
};
|
||||
|
||||
class confack {
|
||||
|
|
|
@ -66,10 +66,14 @@ kvz_rtp::zrtp_msg::confirm::confirm(zrtp_session_t& session, int part)
|
|||
|
||||
aes_cfb->encrypt((uint8_t *)msg->hash, (uint8_t *)msg->hash, 40);
|
||||
|
||||
/* Calculate HMAC-SHA256 of the encrypted portion of the message */
|
||||
hmac_sha256->update((uint8_t *)msg->hash, 40);
|
||||
hmac_sha256->final(mac_full);
|
||||
memcpy(&msg->confirm_mac, mac_full, sizeof(uint64_t));
|
||||
|
||||
/* Calculate CRC32 for the whole ZRTP packet */
|
||||
kvz_rtp::crypto::crc32::get_crc32((uint8_t *)frame_, len_ - 4, &msg->crc);
|
||||
|
||||
delete hmac_sha256;
|
||||
delete aes_cfb;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ namespace kvz_rtp {
|
|||
|
||||
namespace zrtp_msg {
|
||||
|
||||
struct zrtp_hello_ack;
|
||||
struct zrtp_commit;
|
||||
struct zrtp_hello;
|
||||
struct zrtp_dh;
|
||||
|
|
|
@ -78,13 +78,16 @@ kvz_rtp::zrtp_msg::dh_key_exchange::dh_key_exchange(zrtp_session_t& session, int
|
|||
/* public key */
|
||||
memcpy(msg->pk, session.public_key, sizeof(session.public_key));
|
||||
|
||||
/* Finally calculate MAC code for the message */
|
||||
/* Calculate truncated HMAC-SHA256 for the Commit Message */
|
||||
hmac_sha256 = kvz_rtp::crypto::hmac::sha256(session.hashes[0], 32);
|
||||
hmac_sha256.update((uint8_t *)frame_, len_ - 8 - 4);
|
||||
hmac_sha256.final(mac_full);
|
||||
|
||||
memcpy(msg->mac, mac_full, 8);
|
||||
|
||||
/* Calculate CRC32 for the whole ZRTP packet */
|
||||
kvz_rtp::crypto::crc32::get_crc32((uint8_t *)frame_, len_ - 4, &msg->crc);
|
||||
|
||||
/* Finally make a copy of the message and save it for later use */
|
||||
session.l_msg.dh.first = len_;
|
||||
session.l_msg.dh.second = (kvz_rtp::zrtp_msg::zrtp_dh *)new uint8_t[len_];
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
namespace kvz_rtp {
|
||||
|
||||
typedef struct zrtp_session zrtp_session_t;
|
||||
|
||||
namespace zrtp_msg {
|
||||
|
||||
struct zrtp_dh {
|
||||
|
|
|
@ -18,17 +18,22 @@ kvz_rtp::zrtp_msg::hello::hello(zrtp_session_t& session)
|
|||
|
||||
/* We support only the mandatory algorithms etc. defined in RFC 6189
|
||||
* so for us all the hash algos and key agreement types are set to zero */
|
||||
size_t common_size = sizeof(zrtp_hello) - sizeof(zrtp_header);
|
||||
size_t our_size = common_size;
|
||||
/* size_t common_size = sizeof(zrtp_hello) - sizeof(zrtp_header); */
|
||||
/* size_t our_size = common_size; */
|
||||
|
||||
/* assume remote supports everything so allocate space for all possible elements */
|
||||
size_t their_size = common_size + 5 * 8 * sizeof(uint32_t);
|
||||
/* size_t their_size = common_size + 5 * 8 * sizeof(uint32_t); */
|
||||
|
||||
frame_ = kvz_rtp::frame::alloc_zrtp_frame(our_size);
|
||||
rframe_ = kvz_rtp::frame::alloc_zrtp_frame(their_size);
|
||||
len_ = sizeof(zrtp_hello);
|
||||
rlen_ = sizeof(zrtp_hello) + 5 * 8;
|
||||
|
||||
len_ = sizeof(kvz_rtp::frame::zrtp_frame) + our_size;
|
||||
rlen_ = sizeof(kvz_rtp::frame::zrtp_frame) + their_size;
|
||||
frame_ = kvz_rtp::frame::alloc_zrtp_frame(sizeof(zrtp_hello));
|
||||
rframe_ = kvz_rtp::frame::alloc_zrtp_frame(sizeof(zrtp_hello) + 5 * 8);
|
||||
|
||||
memset(frame_, 0, sizeof(zrtp_hello));
|
||||
memset(rframe_, 0, sizeof(zrtp_hello) + 5 * 8);
|
||||
|
||||
fprintf(stderr, "%zu\n", len_);
|
||||
|
||||
zrtp_hello *msg = (zrtp_hello *)frame_;
|
||||
|
||||
|
@ -38,7 +43,7 @@ kvz_rtp::zrtp_msg::hello::hello(zrtp_session_t& session)
|
|||
msg->msg_start.header.seq = session.seq++;
|
||||
|
||||
msg->msg_start.magic = ZRTP_MSG_MAGIC;
|
||||
msg->msg_start.length = our_size;
|
||||
msg->msg_start.length = len_ - sizeof(kvz_rtp::frame::zrtp_frame);
|
||||
|
||||
memcpy(&msg->msg_start.msgblock, ZRTP_HELLO, 8);
|
||||
memcpy(&msg->version, ZRTP_VERSION, 4);
|
||||
|
@ -50,19 +55,23 @@ kvz_rtp::zrtp_msg::hello::hello(zrtp_session_t& session)
|
|||
msg->s = 0;
|
||||
msg->m = 0;
|
||||
msg->p = 0;
|
||||
msg->unused = 0;
|
||||
/* msg->unused = 0; */
|
||||
msg->hc = 0;
|
||||
msg->ac = 0;
|
||||
msg->kc = 0;
|
||||
msg->sc = 0;
|
||||
|
||||
/* Calculate MAC for the Hello message (only the ZRTP message part) */
|
||||
auto hmac_sha256 = kvz_rtp::crypto::hmac::sha256(session.hashes[2], 32);
|
||||
|
||||
hmac_sha256.update((uint8_t *)frame_, our_size - 8);
|
||||
hmac_sha256.update((uint8_t *)frame_, 81);
|
||||
hmac_sha256.final(mac_full);
|
||||
|
||||
memcpy(&msg->mac, mac_full, sizeof(uint64_t));
|
||||
|
||||
/* Calculate CRC32 of the whole packet (excluding crc) */
|
||||
kvz_rtp::crypto::crc32::get_crc32((uint8_t *)frame_, len_ - 4, &msg->crc);
|
||||
|
||||
/* Finally make a copy of the message and save it for later use */
|
||||
session.l_msg.hello.first = len_;
|
||||
session.l_msg.hello.second = (kvz_rtp::zrtp_msg::zrtp_hello *)new uint8_t[len_];
|
||||
|
@ -73,6 +82,7 @@ kvz_rtp::zrtp_msg::hello::~hello()
|
|||
{
|
||||
LOG_DEBUG("Freeing ZRTP hello message...");
|
||||
(void)kvz_rtp::frame::dealloc_frame(frame_);
|
||||
(void)kvz_rtp::frame::dealloc_frame(rframe_);
|
||||
}
|
||||
|
||||
rtp_error_t kvz_rtp::zrtp_msg::hello::send_msg(socket_t& socket, sockaddr_in& addr)
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
namespace kvz_rtp {
|
||||
|
||||
typedef struct capabilities zrtp_capab_t;
|
||||
typedef struct zrtp_session zrtp_session_t;
|
||||
|
||||
namespace zrtp_msg {
|
||||
|
||||
|
@ -39,6 +40,7 @@ namespace kvz_rtp {
|
|||
uint32_t sas_types[0];
|
||||
|
||||
uint64_t mac;
|
||||
uint32_t crc;
|
||||
};
|
||||
|
||||
class hello {
|
||||
|
|
|
@ -14,6 +14,8 @@ kvz_rtp::zrtp_msg::hello_ack::hello_ack()
|
|||
|
||||
zrtp_hello_ack *msg = (zrtp_hello_ack *)frame_;
|
||||
|
||||
memset(msg, 0, sizeof(zrtp_hello_ack));
|
||||
|
||||
msg->msg_start.header.version = 0;
|
||||
msg->msg_start.header.magic = ZRTP_HEADER_MAGIC;
|
||||
|
||||
|
@ -21,6 +23,8 @@ kvz_rtp::zrtp_msg::hello_ack::hello_ack()
|
|||
msg->msg_start.length = 3;
|
||||
|
||||
memcpy(&msg->msg_start.msgblock, ZRTP_HELLO_ACK, 8);
|
||||
|
||||
kvz_rtp::crypto::crc32::get_crc32((uint8_t *)frame_, len_ - 4, &msg->crc);
|
||||
}
|
||||
|
||||
kvz_rtp::zrtp_msg::hello_ack::~hello_ack()
|
||||
|
|
|
@ -9,8 +9,9 @@ namespace kvz_rtp {
|
|||
|
||||
namespace zrtp_msg {
|
||||
|
||||
struct zrtp_hello_ack {
|
||||
PACKED_STRUCT(zrtp_hello_ack) {
|
||||
zrtp_msg msg_start;
|
||||
uint32_t crc;
|
||||
};
|
||||
|
||||
class hello_ack {
|
||||
|
|
|
@ -12,7 +12,14 @@
|
|||
|
||||
#include "debug.hh"
|
||||
#include "util.hh"
|
||||
#include "crypto/crypto.hh"
|
||||
#include "mzrtp/defines.hh"
|
||||
#include "mzrtp/dh_kxchng.hh"
|
||||
#include "mzrtp/commit.hh"
|
||||
#include "mzrtp/confack.hh"
|
||||
#include "mzrtp/confirm.hh"
|
||||
#include "mzrtp/hello.hh"
|
||||
#include "mzrtp/hello_ack.hh"
|
||||
#include "mzrtp/receiver.hh"
|
||||
|
||||
using namespace kvz_rtp::zrtp_msg;
|
||||
|
@ -77,36 +84,92 @@ int kvz_rtp::zrtp_msg::receiver::recv_msg(socket_t& socket, int flags)
|
|||
|
||||
switch (msg->msgblock) {
|
||||
case ZRTP_MSG_HELLO:
|
||||
LOG_DEBUG("Hello message received");
|
||||
return ZRTP_FT_HELLO;
|
||||
{
|
||||
LOG_DEBUG("Hello message received, verify CRC32!");
|
||||
|
||||
zrtp_hello *hello = (zrtp_hello *)msg;
|
||||
|
||||
if (!kvz_rtp::crypto::crc32::verify_crc32(mem_, rlen_ - 4, hello->crc))
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
return ZRTP_FT_HELLO;
|
||||
|
||||
case ZRTP_MSG_HELLO_ACK:
|
||||
LOG_DEBUG("HelloACK message received");
|
||||
return ZRTP_FT_HELLO_ACK;
|
||||
{
|
||||
LOG_DEBUG("HelloACK message received, verify CRC32!");
|
||||
|
||||
zrtp_hello_ack *ha_msg = (zrtp_hello_ack *)msg;
|
||||
|
||||
if (!kvz_rtp::crypto::crc32::verify_crc32(mem_, rlen_ - 4, ha_msg->crc))
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
return ZRTP_FT_HELLO_ACK;
|
||||
|
||||
case ZRTP_MSG_COMMIT:
|
||||
LOG_DEBUG("Commit message received");
|
||||
return ZRTP_FT_COMMIT;
|
||||
{
|
||||
LOG_DEBUG("Commit message received, verify CRC32!");
|
||||
|
||||
zrtp_commit *commit = (zrtp_commit *)msg;
|
||||
|
||||
if (!kvz_rtp::crypto::crc32::verify_crc32(mem_, rlen_ - 4, commit->crc))
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
return ZRTP_FT_COMMIT;
|
||||
|
||||
case ZRTP_MSG_DH_PART1:
|
||||
LOG_DEBUG("DH Part1 message received");
|
||||
return ZRTP_FT_DH_PART1;
|
||||
{
|
||||
LOG_DEBUG("DH Part1 message received, verify CRC32!");
|
||||
|
||||
zrtp_dh *dh = (zrtp_dh *)msg;
|
||||
|
||||
if (!kvz_rtp::crypto::crc32::verify_crc32(mem_, rlen_ - 4, dh->crc))
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
return ZRTP_FT_DH_PART1;
|
||||
|
||||
case ZRTP_MSG_DH_PART2:
|
||||
LOG_DEBUG("DH Part2 message received");
|
||||
return ZRTP_FT_DH_PART2;
|
||||
{
|
||||
LOG_DEBUG("DH Part2 message received, verify CRC32!");
|
||||
|
||||
zrtp_dh *dh = (zrtp_dh *)msg;
|
||||
|
||||
if (!kvz_rtp::crypto::crc32::verify_crc32(mem_, rlen_ - 4, dh->crc))
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
return ZRTP_FT_DH_PART2;
|
||||
|
||||
case ZRTP_MSG_CONFIRM1:
|
||||
LOG_DEBUG("Confirm1 message received");
|
||||
return ZRTP_FT_CONFIRM1;
|
||||
{
|
||||
LOG_DEBUG("Confirm1 message received, verify CRC32!");
|
||||
|
||||
zrtp_confirm *dh = (zrtp_confirm *)msg;
|
||||
|
||||
if (!kvz_rtp::crypto::crc32::verify_crc32(mem_, rlen_ - 4, dh->crc))
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
return ZRTP_FT_CONFIRM1;
|
||||
|
||||
case ZRTP_MSG_CONFIRM2:
|
||||
LOG_DEBUG("Confirm2 message received");
|
||||
return ZRTP_FT_CONFIRM2;
|
||||
{
|
||||
LOG_DEBUG("Confirm2 message received, verify CRC32!");
|
||||
|
||||
zrtp_confirm *dh = (zrtp_confirm *)msg;
|
||||
|
||||
if (!kvz_rtp::crypto::crc32::verify_crc32(mem_, rlen_ - 4, dh->crc))
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
return ZRTP_FT_CONFIRM2;
|
||||
|
||||
case ZRTP_MSG_CONF2_ACK:
|
||||
LOG_DEBUG("Conf2 ACK message received");
|
||||
return ZRTP_FT_CONF2_ACK;
|
||||
{
|
||||
LOG_DEBUG("Conf2 ACK message received, verify CRC32!");
|
||||
|
||||
zrtp_confack *ca = (zrtp_confack *)msg;
|
||||
|
||||
if (!kvz_rtp::crypto::crc32::verify_crc32(mem_, rlen_ - 4, ca->crc))
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
return ZRTP_FT_CONF2_ACK;
|
||||
|
||||
case ZRTP_MSG_ERROR:
|
||||
LOG_DEBUG("Error message received");
|
||||
|
|
12
src/zrtp.cc
12
src/zrtp.cc
|
@ -244,7 +244,7 @@ rtp_error_t kvz_rtp::zrtp::validate_session()
|
|||
if (RTP_INVALID_VALUE == verify_hash(
|
||||
(uint8_t *)hashes[1],
|
||||
(uint8_t *)session_.r_msg.commit.second,
|
||||
session_.r_msg.commit.first - 8,
|
||||
session_.r_msg.commit.first - 8 - 4,
|
||||
session_.remote_macs[2]
|
||||
))
|
||||
{
|
||||
|
@ -307,8 +307,9 @@ rtp_error_t kvz_rtp::zrtp::begin_session()
|
|||
for (i = 0; i < 20; ++i) {
|
||||
set_timeout(rto);
|
||||
|
||||
if ((ret = hello.send_msg(socket_, addr_)) != RTP_OK)
|
||||
if ((ret = hello.send_msg(socket_, addr_)) != RTP_OK) {
|
||||
LOG_ERROR("Failed to send Hello message");
|
||||
}
|
||||
|
||||
if ((type = receiver_.recv_msg(socket_, 0)) > 0) {
|
||||
/* We received something interesting, either Hello message from remote in which case
|
||||
|
@ -383,8 +384,9 @@ rtp_error_t kvz_rtp::zrtp::init_session()
|
|||
for (int i = 0; i < 10; ++i) {
|
||||
set_timeout(rto);
|
||||
|
||||
if ((ret = commit.send_msg(socket_, addr_)) != RTP_OK)
|
||||
if ((ret = commit.send_msg(socket_, addr_)) != RTP_OK) {
|
||||
LOG_ERROR("Failed to send Commit message!");
|
||||
}
|
||||
|
||||
if ((type = receiver_.recv_msg(socket_, 0)) > 0) {
|
||||
|
||||
|
@ -471,8 +473,9 @@ rtp_error_t kvz_rtp::zrtp::dh_part2()
|
|||
for (int i = 0; i < 10; ++i) {
|
||||
set_timeout(rto);
|
||||
|
||||
if ((ret = dhpart.send_msg(socket_, addr_)) != RTP_OK)
|
||||
if ((ret = dhpart.send_msg(socket_, addr_)) != RTP_OK) {
|
||||
LOG_ERROR("Failed to send DHPart2 Message!");
|
||||
}
|
||||
|
||||
if ((type = receiver_.recv_msg(socket_, 0)) > 0) {
|
||||
if (type == ZRTP_FT_CONFIRM1) {
|
||||
|
@ -571,6 +574,7 @@ rtp_error_t kvz_rtp::zrtp::init(uint32_t ssrc, socket_t& socket, sockaddr_in& ad
|
|||
rtp_error_t ret = RTP_OK;
|
||||
|
||||
/* TODO: set all fields initially to zero */
|
||||
memset(session_.hvi, 0, sizeof(session_.hvi));
|
||||
|
||||
generate_zid();
|
||||
generate_secrets();
|
||||
|
|
Loading…
Reference in New Issue