]> git.meshlink.io Git - meshlink/blobdiff - src/sptps.c
Move the routing header out of the SPTPS payload.
[meshlink] / src / sptps.c
index 3bc811ed207e3f80da255e7c85d375d431804b62..a83382562abd5f4ec67171e6cf6bb2442df8a537 100644 (file)
@@ -106,6 +106,7 @@ static bool send_record_priv_datagram(sptps_t *s, uint8_t type, const void *data
                return s->send_data(s->handle, type, buffer, len + 5UL);
        }
 }
+
 // Send a record (private version, accepts all record types, handles encryption and authentication).
 static bool send_record_priv(sptps_t *s, uint8_t type, const void *data, uint16_t len) {
        if(s->datagram) {
@@ -147,6 +148,38 @@ bool sptps_send_record(sptps_t *s, uint8_t type, const void *data, uint16_t len)
        return send_record_priv(s, type, data, len);
 }
 
+// Pass through unencrypted data.
+bool sptps_send_unencrypted(sptps_t *s, const void *data, uint16_t len) {
+       // Sanity checks: application cannot send data before handshake is finished,
+       // and only non-datagram allowed.
+       if(!s->outstate) {
+               return error(s, EINVAL, "Handshake phase not finished yet");
+       }
+
+       if(s->datagram) {
+               return error(s, EINVAL, "Not allowed for datagrams");
+       }
+
+       return s->send_data(s->handle, SPTPS_UNENCRYPTED, data, len);
+}
+
+// Expect a given number of unencrypted bytes.
+bool sptps_expect_unencrypted(sptps_t *s, uint16_t len) {
+       // Sanity checks: application cannot send data before handshake is finished,
+       // and only non-datagram allowed.
+       if(!s->instate) {
+               return error(s, EINVAL, "Handshake phase not finished yet");
+       }
+
+       if(s->datagram) {
+               return error(s, EINVAL, "Not allowed for datagrams");
+       }
+
+       s->reclen = len;
+       s->passthrough = true;
+       return true;
+}
+
 // Send a Key EXchange record, containing a random nonce and an ECDHE public key.
 static bool send_kex(sptps_t *s) {
        size_t keylen = ECDH_SIZE;
@@ -447,7 +480,7 @@ bool sptps_verify_datagram(sptps_t *s, const void *data, size_t len) {
 
        char buffer[len];
        size_t outlen;
-       return chacha_poly1305_decrypt(s->incipher, seqno, data + 4, len - 4, buffer, &outlen);
+       return chacha_poly1305_decrypt(s->incipher, seqno, (const char *)data + 4, len - 4, buffer, &outlen);
 }
 
 // Receive incoming data, datagram version.
@@ -561,7 +594,49 @@ bool sptps_receive_data(sptps_t *s, const void *data, size_t len) {
                return sptps_receive_data_datagram(s, data, len);
        }
 
+       const char *ptr = data;
+
        while(len) {
+               if(s->passthrough) {
+                       if(!s->buflen && s->reclen <= len) {
+                               len -= s->reclen;
+                               ptr += s->reclen;
+
+                               s->reclen = 0;
+                               s->passthrough = false;
+
+                               if(!s->receive_record(s->handle, SPTPS_UNENCRYPTED, data, s->reclen)) {
+                                       return false;
+                               }
+
+                               continue;
+                       }
+
+                       size_t toread = s->reclen - s->buflen;
+                       if (toread >= len) {
+                               toread = len;
+                       }
+
+                       memcpy(s->inbuf + s->buflen, ptr, toread);
+                       s->buflen += toread;
+                       len -= toread;
+                       ptr += toread;
+
+                       if(s->buflen < s->reclen) {
+                               return;
+                       }
+
+                       s->reclen = 0;
+                       s->passthrough = false;
+
+                       if(!s->receive_record(s->handle, SPTPS_UNENCRYPTED, data, s->reclen)) {
+                               return false;
+                       }
+
+                       s->buflen = 0;
+                       continue;
+               }
+
                // First read the 2 length bytes.
                if(s->buflen < 2) {
                        size_t toread = 2 - s->buflen;
@@ -570,11 +645,11 @@ bool sptps_receive_data(sptps_t *s, const void *data, size_t len) {
                                toread = len;
                        }
 
-                       memcpy(s->inbuf + s->buflen, data, toread);
+                       memcpy(s->inbuf + s->buflen, ptr, toread);
 
                        s->buflen += toread;
                        len -= toread;
-                       data += toread;
+                       ptr += toread;
 
                        // Exit early if we don't have the full length.
                        if(s->buflen < 2) {
@@ -606,10 +681,10 @@ bool sptps_receive_data(sptps_t *s, const void *data, size_t len) {
                        toread = len;
                }
 
-               memcpy(s->inbuf + s->buflen, data, toread);
+               memcpy(s->inbuf + s->buflen, ptr, toread);
                s->buflen += toread;
                len -= toread;
-               data += toread;
+               ptr += toread;
 
                // If we don't have a whole record, exit.
                if(s->buflen < s->reclen + (s->instate ? 19UL : 3UL)) {