-Subproject commit 08ac450b42b7533e97c02c02bbbef8946b9582fb
+Subproject commit bb173469810e4c7de19e53793d4af2e27e6e222c
return true;
}
+bool chacha_poly1305_verify(chacha_poly1305_ctx_t *ctx, uint64_t seqnr, const void *indata, size_t inlen) {
+ uint8_t seqbuf[8];
+ uint8_t expected_tag[POLY1305_TAGLEN], poly_key[POLY1305_KEYLEN];
+
+ /*
+ * Run ChaCha20 once to generate the Poly1305 key. The IV is the
+ * packet sequence number.
+ */
+ memset(poly_key, 0, sizeof(poly_key));
+ put_u64(seqbuf, seqnr);
+ chacha_ivsetup(&ctx->main_ctx, seqbuf, NULL);
+ chacha_encrypt_bytes(&ctx->main_ctx, poly_key, poly_key, sizeof(poly_key));
+
+ /* Check tag before anything else */
+ inlen -= POLY1305_TAGLEN;
+ const uint8_t *tag = (const uint8_t *)indata + inlen;
+
+ poly1305_auth(expected_tag, indata, inlen, poly_key);
+ if (memcmp(expected_tag, tag, POLY1305_TAGLEN))
+ return false;
+
+ return true;
+}
+
bool chacha_poly1305_decrypt(chacha_poly1305_ctx_t *ctx, uint64_t seqnr, const void *indata, size_t inlen, void *outdata, size_t *outlen) {
uint8_t seqbuf[8];
const uint8_t one[8] = { 1, 0, 0, 0, 0, 0, 0, 0 }; /* NB little-endian */
extern bool chacha_poly1305_set_key(chacha_poly1305_ctx_t *ctx, const void *key);
extern bool chacha_poly1305_encrypt(chacha_poly1305_ctx_t *ctx, uint64_t seqnr, const void *indata, size_t inlen, void *outdata, size_t *outlen);
+extern bool chacha_poly1305_verify(chacha_poly1305_ctx_t *ctx, uint64_t seqnr, const void *indata, size_t inlen);
extern bool chacha_poly1305_decrypt(chacha_poly1305_ctx_t *ctx, uint64_t seqnr, const void *indata, size_t inlen, void *outdata, size_t *outlen);
extern bool chacha_poly1305_encrypt_iv96(chacha_poly1305_ctx_t *ctx, const uint8_t *seqbuf, const void *indata, size_t inlen, void *outdata, size_t *outlen);
}
/* Create a temporary struct on the stack, to avoid allocating and freeing one. */
- meshlink_open_params_t params = {NULL};
+ meshlink_open_params_t params;
+ memset(¶ms, 0, sizeof(params));
params.confbase = (char *)confbase;
params.name = (char *)name;
meshlink_handle_t *meshlink_open_ephemeral(const char *name, const char *appname, dev_class_t devclass) {
/* Create a temporary struct on the stack, to avoid allocating and freeing one. */
- meshlink_open_params_t params = {NULL};
+ meshlink_open_params_t params;
+ memset(¶ms, 0, sizeof(params));
params.name = (char *)name;
params.appname = (char *)appname;
* Note: make sure we only add config files of nodes that are in the core mesh or the same submesh,
* and are not blacklisted.
*/
- config_t configs[5] = {NULL};
+ config_t configs[5];
+ memset(configs, 0, sizeof(configs));
int count = 0;
if(config_read(mesh, "current", mesh->self->name, &configs[count], mesh->config_key)) {
}
if(n->status.blacklisted) {
- logger(mesh, MESHLINK_EPEER, "Peer %s is blacklisted", c->name);
+ logger(mesh, MESHLINK_WARNING, "Peer %s is blacklisted", c->name);
return false;
}
seqno = ntohl(seqno);
// TODO: check whether seqno makes sense, to avoid CPU intensive decrypt
- char buffer[len];
- size_t outlen;
- return chacha_poly1305_decrypt(s->incipher, seqno, (const char *)data + 4, len - 4, buffer, &outlen);
+ return chacha_poly1305_verify(s->incipher, seqno, (const char *)data + 4, len - 4);
}
// Receive incoming data, datagram version.
// Decrypt
- char buffer[len];
+ if(len > s->decrypted_buffer_len) {
+ s->decrypted_buffer_len *= 2;
+ char *new_buffer = realloc(s->decrypted_buffer, s->decrypted_buffer_len);
+
+ if(!new_buffer) {
+ return error(s, errno, strerror(errno));
+ }
+
+ s->decrypted_buffer = new_buffer;
+ }
size_t outlen;
- if(!chacha_poly1305_decrypt(s->incipher, seqno, data + 4, len - 4, buffer, &outlen)) {
+ if(!chacha_poly1305_decrypt(s->incipher, seqno, data + 4, len - 4, s->decrypted_buffer, &outlen)) {
return error(s, EIO, "Failed to decrypt and verify packet");
}
}
// Append a NULL byte for safety.
- buffer[len - 20] = 0;
+ s->decrypted_buffer[len - 20] = 0;
- uint8_t type = buffer[0];
+ uint8_t type = s->decrypted_buffer[0];
if(type < SPTPS_HANDSHAKE) {
if(!s->instate) {
return error(s, EIO, "Application record received before handshake finished");
}
- if(!s->receive_record(s->handle, type, buffer + 1, len - 21)) {
+ if(!s->receive_record(s->handle, type, s->decrypted_buffer + 1, len - 21)) {
abort();
}
} else if(type == SPTPS_HANDSHAKE) {
- if(!receive_handshake(s, buffer + 1, len - 21)) {
+ if(!receive_handshake(s, s->decrypted_buffer + 1, len - 21)) {
abort();
}
} else {
s->mykey = mykey;
s->hiskey = hiskey;
s->replaywin = 32;
+ s->decrypted_buffer_len = 1024;
+ s->decrypted_buffer = malloc(s->decrypted_buffer_len);
+
+ if(!s->decrypted_buffer) {
+ return error(s, errno, strerror(errno));
+ }
if(s->replaywin) {
s->late = malloc(s->replaywin);
free(s->key);
free(s->label);
free(s->late);
+ memset(s->decrypted_buffer, 0, s->decrypted_buffer_len);
+ free(s->decrypted_buffer);
memset(s, 0, sizeof(*s));
return true;
}
char *late;
+ char *decrypted_buffer;
+ size_t decrypted_buffer_len;
+
// Callbacks
void *handle;
send_data_t send_data;