X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=src%2Fsptps.c;h=50958ec64737743329664d376c1ee009469532ee;hb=b0f7726931e9339e91b8d49941626f015015bd98;hp=99a3cea9fca47049bd070f6f3e0c0cc1f0452174;hpb=43ed5b9a5d739c50317d5d24898de07526a9297f;p=meshlink diff --git a/src/sptps.c b/src/sptps.c index 99a3cea9..50958ec6 100644 --- a/src/sptps.c +++ b/src/sptps.c @@ -27,7 +27,7 @@ #include "prf.h" #include "sptps.h" -unsigned int sptps_replaywin = 16; +unsigned int sptps_replaywin = 32; /* Nonce MUST be exchanged first (done) @@ -177,11 +177,11 @@ static bool send_sig(sptps_t *s) { memcpy(msg + 1 + 2 * (33 + keylen), s->label, s->labellen); // Sign the result. - if(!ecdsa_sign(s->mykey, msg, sizeof msg, sig)) + if(!ecdsa_sign(s->mykey, msg, sizeof(msg), sig)) return error(s, EINVAL, "Failed to sign SIG record"); // Send the SIG exchange record. - return send_record_priv(s, SPTPS_HANDSHAKE, sig, sizeof sig); + return send_record_priv(s, SPTPS_HANDSHAKE, sig, sizeof(sig)); } // Generate key material from the shared secret created from the ECDHE key exchange. @@ -283,7 +283,7 @@ static bool receive_sig(sptps_t *s, const char *data, uint16_t len) { memcpy(msg + 1 + 2 * (33 + keylen), s->label, s->labellen); // Verify signature. - if(!ecdsa_verify(s->hiskey, msg, sizeof msg, data)) + if(!ecdsa_verify(s->hiskey, msg, sizeof(msg), data)) return error(s, EIO, "Failed to verify SIG record"); // Compute shared secret. @@ -293,7 +293,7 @@ static bool receive_sig(sptps_t *s, const char *data, uint16_t len) { s->ecdh = NULL; // Generate key material from shared secret. - if(!generate_key_material(s, shared, sizeof shared)) + if(!generate_key_material(s, shared, sizeof(shared))) return false; free(s->mykex); @@ -331,52 +331,52 @@ bool sptps_force_kex(sptps_t *s) { static bool receive_handshake(sptps_t *s, const char *data, uint16_t len) { // Only a few states to deal with handshaking. switch(s->state) { - case SPTPS_SECONDARY_KEX: - // We receive a secondary KEX request, first respond by sending our own. - if(!send_kex(s)) - return false; - case SPTPS_KEX: - // We have sent our KEX request, we expect our peer to sent one as well. - if(!receive_kex(s, data, len)) - return false; - s->state = SPTPS_SIG; - return true; - case SPTPS_SIG: - // If we already sent our secondary public ECDH key, we expect the peer to send his. - if(!receive_sig(s, data, len)) - return false; - if(s->outstate) - s->state = SPTPS_ACK; - else { - s->outstate = true; - if(!receive_ack(s, NULL, 0)) - return false; - s->receive_record(s->handle, SPTPS_HANDSHAKE, NULL, 0); - s->state = SPTPS_SECONDARY_KEX; - } - - return true; - case SPTPS_ACK: - // We expect a handshake message to indicate transition to the new keys. - if(!receive_ack(s, data, len)) + case SPTPS_SECONDARY_KEX: + // We receive a secondary KEX request, first respond by sending our own. + if(!send_kex(s)) + return false; + case SPTPS_KEX: + // We have sent our KEX request, we expect our peer to sent one as well. + if(!receive_kex(s, data, len)) + return false; + s->state = SPTPS_SIG; + return true; + case SPTPS_SIG: + // If we already sent our secondary public ECDH key, we expect the peer to send his. + if(!receive_sig(s, data, len)) + return false; + if(s->outstate) + s->state = SPTPS_ACK; + else { + s->outstate = true; + if(!receive_ack(s, NULL, 0)) return false; s->receive_record(s->handle, SPTPS_HANDSHAKE, NULL, 0); s->state = SPTPS_SECONDARY_KEX; - return true; - // TODO: split ACK into a VERify and ACK? - default: - return error(s, EIO, "Invalid session state %d", s->state); + } + + return true; + case SPTPS_ACK: + // We expect a handshake message to indicate transition to the new keys. + if(!receive_ack(s, data, len)) + return false; + s->receive_record(s->handle, SPTPS_HANDSHAKE, NULL, 0); + s->state = SPTPS_SECONDARY_KEX; + return true; + // TODO: split ACK into a VERify and ACK? + default: + return error(s, EIO, "Invalid session state %d", s->state); } } // Check datagram for valid HMAC bool sptps_verify_datagram(sptps_t *s, const void *data, size_t len) { + if(!s->instate) + return error(s, EIO, "SPTPS state not ready to verify this datagram"); + if(len < 21) return error(s, EIO, "Received short packet in sptps_verify_datagram"); - if (!s->instate) - return error(s, EIO, "SPTPS state not ready to verify this datagram"); - uint32_t seqno; memcpy(&seqno, data, 4); seqno = ntohl(seqno); @@ -391,12 +391,9 @@ bool sptps_verify_datagram(sptps_t *s, const void *data, size_t len) { static bool sptps_receive_data_datagram(sptps_t *s, const void *vdata, size_t len) { const char *data = vdata; - if(len < 21) + if(len < (s->instate ? 21 : 5)) return error(s, EIO, "Received short packet in sptps_receive_data_datagram"); - if (!s->instate) - return error(s, EIO, "SPTPS state not ready to verify this datagram"); - uint32_t seqno; memcpy(&seqno, data, 4); seqno = ntohl(seqno); @@ -436,7 +433,7 @@ static bool sptps_receive_data_datagram(sptps_t *s, const void *vdata, size_t le warning(s, "Lost %d packets\n", seqno - s->inseqno); // Mark all packets in the replay window as being late. memset(s->late, 255, s->replaywin); - } else if (seqno < s->inseqno) { + } else if(seqno < s->inseqno) { // If the sequence number is farther in the past than the bitmap goes, or if the packet was already received, drop it. if((s->inseqno >= s->replaywin * 8 && seqno < s->inseqno - s->replaywin * 8) || !(s->late[(seqno / 8) % s->replaywin] & (1 << seqno % 8))) return error(s, EIO, "Received late or replayed packet, seqno %d, last received %d\n", seqno, s->inseqno); @@ -472,9 +469,8 @@ static bool sptps_receive_data_datagram(sptps_t *s, const void *vdata, size_t le } else if(type == SPTPS_HANDSHAKE) { if(!receive_handshake(s, buffer + 1, len - 21)) abort(); - } else { + } else return error(s, EIO, "Invalid record type %d", type); - } return true; } @@ -556,9 +552,8 @@ bool sptps_receive_data(sptps_t *s, const void *data, size_t len) { } else if(type == SPTPS_HANDSHAKE) { if(!receive_handshake(s, s->inbuf + 3, s->reclen)) return false; - } else { + } else return error(s, EIO, "Invalid record type %d", type); - } s->buflen = 0; } @@ -568,8 +563,11 @@ bool sptps_receive_data(sptps_t *s, const void *data, size_t len) { // Start a SPTPS session. bool sptps_start(sptps_t *s, void *handle, bool initiator, bool datagram, ecdsa_t *mykey, ecdsa_t *hiskey, const char *label, size_t labellen, send_data_t send_data, receive_record_t receive_record) { + if(!s || !mykey || !hiskey || !label || !labellen || !send_data || !receive_record) + return error(s, EINVAL, "Invalid argument to sptps_start()"); + // Initialise struct sptps - memset(s, 0, sizeof *s); + memset(s, 0, sizeof(*s)); s->handle = handle; s->initiator = initiator; @@ -618,6 +616,6 @@ bool sptps_stop(sptps_t *s) { free(s->key); free(s->label); free(s->late); - memset(s, 0, sizeof *s); + memset(s, 0, sizeof(*s)); return true; }