OverviewFilesCommitsIssuesDocsReleasesPeers

hyperswarm-peer / src / noise_stream.cpp

79 lines · cpp ref:
#include "noise_stream.h"

#include <cstring>

NoiseStream::NoiseStream()
	: _tx_init(false), _rx_init(false) {
	memset(&_tx_state, 0, sizeof(_tx_state));
	memset(&_rx_state, 0, sizeof(_rx_state));
	memset(_tx_header, 0, HEADER_BYTES);
}

NoiseStream::~NoiseStream() {
	sodium_memzero(&_tx_state, sizeof(_tx_state));
	sodium_memzero(&_rx_state, sizeof(_rx_state));
	sodium_memzero(_tx_header, HEADER_BYTES);
}

void NoiseStream::init_tx(const uint8_t *key) {
	crypto_secretstream_xchacha20poly1305_init_push(&_tx_state, _tx_header, key);
	_tx_init = true;
}

bool NoiseStream::init_rx(const uint8_t *key, const uint8_t *header) {
	int ret = crypto_secretstream_xchacha20poly1305_init_pull(&_rx_state, header, key);
	_rx_init = (ret == 0);
	return _rx_init;
}

std::vector<uint8_t> NoiseStream::encrypt(const uint8_t *data, size_t len) {
	std::vector<uint8_t> ct(len + TAG_BYTES);
	unsigned long long ct_len;
	crypto_secretstream_xchacha20poly1305_push(
		&_tx_state,
		ct.data(), &ct_len,
		data, len,
		nullptr, 0, // no additional data
		0            // tag: MESSAGE (not FINAL)
	);
	ct.resize(static_cast<size_t>(ct_len));
	return ct;
}

bool NoiseStream::decrypt(const uint8_t *data, size_t len, std::vector<uint8_t> &out) {
	out.clear();
	if (len < TAG_BYTES) return false;

	std::vector<uint8_t> pt(len - TAG_BYTES);
	unsigned long long pt_len;
	unsigned char tag;
	int ret = crypto_secretstream_xchacha20poly1305_pull(
		&_rx_state,
		pt.data(), &pt_len, &tag,
		data, len,
		nullptr, 0 // no additional data
	);
	if (ret != 0) return false; // Authentication failure.
	pt.resize(static_cast<size_t>(pt_len));
	out.swap(pt);
	return true;
}

std::vector<uint8_t> NoiseStream::decrypt(const uint8_t *data, size_t len) {
	if (len < TAG_BYTES) return {};

	std::vector<uint8_t> pt(len - TAG_BYTES);
	unsigned long long pt_len;
	unsigned char tag;
	int ret = crypto_secretstream_xchacha20poly1305_pull(
		&_rx_state,
		pt.data(), &pt_len, &tag,
		data, len,
		nullptr, 0 // no additional data
	);

	if (ret != 0) return {}; // Authentication failure.
	pt.resize(static_cast<size_t>(pt_len));
	return pt;
}