X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=src%2Fsptps.c;h=133f2b7e043b24235a16db83692aa1a32f7d0c34;hb=03aafb2c9ea38c9baf9bc0672001ffe38c91c47d;hp=54c5a55e61bc27ed7eff8aec95803c4d3181842e;hpb=f619a7412c1aeebcdeb98cb95244a9eed5d9b537;p=meshlink diff --git a/src/sptps.c b/src/sptps.c index 54c5a55e..133f2b7e 100644 --- a/src/sptps.c +++ b/src/sptps.c @@ -19,7 +19,7 @@ #include "system.h" -#include "cipher.h" +#include "chacha-poly1305/chacha-poly1305.h" #include "crypto.h" #include "ecdh.h" #include "ecdsa.h" @@ -84,26 +84,19 @@ static bool send_record_priv_datagram(sptps_t *s, uint8_t type, const char *data char buffer[len + 21UL]; // Create header with sequence number, length and record type - uint32_t seqno = htonl(s->outseqno++); + uint32_t seqno = s->outseqno++; + uint32_t netseqno = ntohl(seqno); - memcpy(buffer, &seqno, 4); + memcpy(buffer, &netseqno, 4); buffer[4] = type; + memcpy(buffer + 5, data, len); if(s->outstate) { // If first handshake has finished, encrypt and HMAC - if(!cipher_set_counter(s->outcipher, &seqno, sizeof seqno)) - return error(s, EINVAL, "Failed to set counter"); - - if(!cipher_gcm_encrypt_start(s->outcipher, buffer + 4, 1, buffer + 4, NULL)) - return error(s, EINVAL, "Error encrypting record"); - - if(!cipher_gcm_encrypt_finish(s->outcipher, data, len, buffer + 5, NULL)) - return error(s, EINVAL, "Error encrypting record"); - + chacha_poly1305_encrypt(s->outcipher, seqno, buffer + 4, len + 1, buffer + 4, NULL); return s->send_data(s->handle, type, buffer, len + 21UL); } else { // Otherwise send as plaintext - memcpy(buffer + 5, data, len); return s->send_data(s->handle, type, buffer, len + 5UL); } } @@ -115,27 +108,19 @@ static bool send_record_priv(sptps_t *s, uint8_t type, const char *data, uint16_ char buffer[len + 19UL]; // Create header with sequence number, length and record type - uint32_t seqno = htonl(s->outseqno++); + uint32_t seqno = s->outseqno++; uint16_t netlen = htons(len); memcpy(buffer, &netlen, 2); buffer[2] = type; + memcpy(buffer + 3, data, len); if(s->outstate) { // If first handshake has finished, encrypt and HMAC - if(!cipher_set_counter(s->outcipher, &seqno, 4)) - return error(s, EINVAL, "Failed to set counter"); - - if(!cipher_gcm_encrypt_start(s->outcipher, buffer, 3, buffer, NULL)) - return error(s, EINVAL, "Error encrypting record"); - - if(!cipher_gcm_encrypt_finish(s->outcipher, data, len, buffer + 3, NULL)) - return error(s, EINVAL, "Error encrypting record"); - + chacha_poly1305_encrypt(s->outcipher, seqno, buffer + 2, len + 1, buffer + 2, NULL); return s->send_data(s->handle, type, buffer, len + 19UL); } else { // Otherwise send as plaintext - memcpy(buffer + 3, data, len); return s->send_data(s->handle, type, buffer, len + 3UL); } } @@ -203,14 +188,14 @@ static bool send_sig(sptps_t *s) { static bool generate_key_material(sptps_t *s, const char *shared, size_t len) { // Initialise cipher and digest structures if necessary if(!s->outstate) { - s->incipher = cipher_open_by_name("aes-256-gcm"); - s->outcipher = cipher_open_by_name("aes-256-gcm"); + s->incipher = chacha_poly1305_init(); + s->outcipher = chacha_poly1305_init(); if(!s->incipher || !s->outcipher) return error(s, EINVAL, "Failed to open cipher"); } // Allocate memory for key material - size_t keylen = cipher_keylength(s->incipher) + cipher_keylength(s->outcipher); + size_t keylen = 2 * CHACHA_POLY1305_KEYLEN; s->key = realloc(s->key, keylen); if(!s->key) @@ -246,10 +231,10 @@ static bool receive_ack(sptps_t *s, const char *data, uint16_t len) { return error(s, EIO, "Invalid ACK record length"); if(s->initiator) { - if(!cipher_set_counter_key(s->incipher, s->key)) + if(!chacha_poly1305_set_key(s->incipher, s->key)) return error(s, EINVAL, "Failed to set counter"); } else { - if(!cipher_set_counter_key(s->incipher, s->key + cipher_keylength(s->outcipher))) + if(!chacha_poly1305_set_key(s->incipher, s->key + CHACHA_POLY1305_KEYLEN)) return error(s, EINVAL, "Failed to set counter"); } @@ -323,11 +308,11 @@ static bool receive_sig(sptps_t *s, const char *data, uint16_t len) { // TODO: only set new keys after ACK has been set/received if(s->initiator) { - if(!cipher_set_counter_key(s->outcipher, s->key + cipher_keylength(s->incipher))) - return error(s, EINVAL, "Failed to set counter"); + if(!chacha_poly1305_set_key(s->outcipher, s->key + CHACHA_POLY1305_KEYLEN)) + return error(s, EINVAL, "Failed to set key"); } else { - if(!cipher_set_counter_key(s->outcipher, s->key)) - return error(s, EINVAL, "Failed to set counter"); + if(!chacha_poly1305_set_key(s->outcipher, s->key)) + return error(s, EINVAL, "Failed to set key"); } return true; @@ -421,11 +406,9 @@ static bool sptps_receive_data_datagram(sptps_t *s, const char *data, size_t len char buffer[len]; - if(!cipher_set_counter(s->incipher, data, sizeof seqno)) - return error(s, EINVAL, "Failed to set counter"); size_t outlen; - if(!cipher_gcm_decrypt(s->incipher, data + 4, len - 4, buffer, &outlen)) + if(!chacha_poly1305_decrypt(s->incipher, seqno, data + 4, len - 4, buffer, &outlen)) return error(s, EIO, "Failed to decrypt and verify packet"); // Replay protection using a sliding window of configurable size. @@ -508,22 +491,9 @@ bool sptps_receive_data(sptps_t *s, const char *data, size_t len) { if(s->buflen < 2) return true; - // Update sequence number. - - uint32_t seqno = htonl(s->inseqno++); - - // Decrypt the length bytes - - if(s->instate) { - if(!cipher_set_counter(s->incipher, &seqno, 4)) - return error(s, EINVAL, "Failed to set counter"); - - if(!cipher_gcm_decrypt_start(s->incipher, s->inbuf, 2, &s->reclen, NULL)) - return error(s, EINVAL, "Failed to decrypt record"); - } else { - memcpy(&s->reclen, s->inbuf, 2); - } + // Get the length bytes + memcpy(&s->reclen, s->inbuf, 2); s->reclen = ntohs(s->reclen); // If we have the length bytes, ensure our buffer can hold the whole request. @@ -550,9 +520,13 @@ bool sptps_receive_data(sptps_t *s, const char *data, size_t len) { if(s->buflen < s->reclen + (s->instate ? 19UL : 3UL)) return true; + // Update sequence number. + + uint32_t seqno = s->inseqno++; + // Check HMAC and decrypt. if(s->instate) { - if(!cipher_gcm_decrypt_finish(s->incipher, s->inbuf + 2UL, s->reclen + 17UL, s->inbuf + 2UL, NULL)) + if(!chacha_poly1305_decrypt(s->incipher, seqno, s->inbuf + 2UL, s->reclen + 17UL, s->inbuf + 2UL, NULL)) return error(s, EINVAL, "Failed to decrypt and verify record"); } @@ -622,10 +596,8 @@ bool sptps_start(sptps_t *s, void *handle, bool initiator, bool datagram, ecdsa_ // Stop a SPTPS session. bool sptps_stop(sptps_t *s) { // Clean up any resources. - cipher_close(s->incipher); - cipher_close(s->outcipher); - digest_close(s->indigest); - digest_close(s->outdigest); + chacha_poly1305_exit(s->incipher); + chacha_poly1305_exit(s->outcipher); ecdh_free(s->ecdh); free(s->inbuf); free(s->mykex);