summaryrefslogtreecommitdiff
path: root/satp
diff options
context:
space:
mode:
authorChristian Pointner <equinox@anytun.org>2017-09-02 03:24:41 +0200
committerChristian Pointner <equinox@anytun.org>2017-09-02 03:24:41 +0200
commit10212b0f9e7c5b2e3166d927cadbc4824f494bd3 (patch)
tree744951c3f1ae6b30b58d5432959c0ac33313f88d /satp
parentmake interface config more modular (diff)
addes first simple satp packets
Diffstat (limited to 'satp')
-rw-r--r--satp/packet.go146
-rw-r--r--satp/packet_test.go187
2 files changed, 333 insertions, 0 deletions
diff --git a/satp/packet.go b/satp/packet.go
new file mode 100644
index 0000000..a24b69a
--- /dev/null
+++ b/satp/packet.go
@@ -0,0 +1,146 @@
+//
+// Copyright (c) 2017 anygone contributors (see AUTHORS file)
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// * Neither the name of anygone nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+
+package satp
+
+import (
+ "bytes"
+ "encoding/binary"
+ "errors"
+)
+
+// 0 1 2 3
+// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | sequence number | |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
+// | sender ID | MUX | |
+// +#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+ |
+// | | payload type | | |
+// | +-------------------------------+ | |
+// | | .... payload ... | |
+// | | +-------------------------------+ |
+// | | | padding (OPT) | pad count(OPT)| |
+// +#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+-+
+// | : authentication tag (RECOMMENDED) : |
+// | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
+// | |
+// +- Encrypted Portion Authenticated Portion ---+
+
+type PlainPacket struct {
+ Type uint16
+ Payload []byte
+}
+
+func NewPlainPacket(PayloadType uint16) (pp *PlainPacket) {
+ pp = &PlainPacket{}
+ pp.Type = PayloadType
+ return
+}
+
+func (pp *PlainPacket) MarshalBinary() (data []byte, err error) {
+ buf := &bytes.Buffer{}
+ if err = binary.Write(buf, binary.BigEndian, pp.Type); err != nil {
+ return
+ }
+ buf.Write(pp.Payload) // returned error is always nil
+ return buf.Bytes(), nil
+}
+
+func (pp *PlainPacket) UnmarshalBinary(data []byte) (err error) {
+ buf := bytes.NewReader(data)
+ if err = binary.Read(buf, binary.BigEndian, &(pp.Type)); err != nil {
+ return
+ }
+ if buf.Len() > 0 {
+ pp.Payload = make([]byte, buf.Len())
+ buf.Read(pp.Payload)
+ }
+ return
+}
+
+type EncryptedPacket struct {
+ SequenceNumber uint32
+ SenderID uint16
+ Mux uint16
+ Payload []byte
+ AuthTag []byte
+}
+
+func NewEncryptedPacket(AuthTagLength uint) (ep *EncryptedPacket) {
+ ep = &EncryptedPacket{}
+ ep.AuthTag = make([]byte, AuthTagLength)
+ return
+}
+
+func (ep *EncryptedPacket) MarshalBinary() (data []byte, err error) {
+ buf := &bytes.Buffer{}
+ if err = binary.Write(buf, binary.BigEndian, ep.SequenceNumber); err != nil {
+ return
+ }
+ if err = binary.Write(buf, binary.BigEndian, ep.SenderID); err != nil {
+ return
+ }
+ if err = binary.Write(buf, binary.BigEndian, ep.Mux); err != nil {
+ return
+ }
+ if len(ep.Payload) >= 2 { // Payload must at least have a payload type which is a uint16 -> 2 bytes
+ buf.Write(ep.Payload) // returned error is always nil
+ } else {
+ return nil, errors.New("Unable to marshal packet: payload is empty/too short")
+ }
+
+ if len(ep.AuthTag) > 0 {
+ buf.Write(ep.AuthTag) // returned error is always nil
+ }
+ return buf.Bytes(), nil
+}
+
+func (ep *EncryptedPacket) UnmarshalBinary(data []byte) (err error) {
+ buf := bytes.NewReader(data)
+ if err = binary.Read(buf, binary.BigEndian, &(ep.SequenceNumber)); err != nil {
+ return
+ }
+ if err = binary.Read(buf, binary.BigEndian, &(ep.SenderID)); err != nil {
+ return
+ }
+ if err = binary.Read(buf, binary.BigEndian, &(ep.Mux)); err != nil {
+ return
+ }
+
+ if (buf.Len() - len(ep.AuthTag)) < 2 { // 2 bytes payload type + length of AuthTag must be left on buffer
+ return errors.New("Unable to unmarshal packet: too short")
+ }
+
+ ep.Payload = make([]byte, buf.Len()-len(ep.AuthTag))
+ buf.Read(ep.Payload)
+ buf.Read(ep.AuthTag)
+ return
+}
diff --git a/satp/packet_test.go b/satp/packet_test.go
new file mode 100644
index 0000000..5fce4f4
--- /dev/null
+++ b/satp/packet_test.go
@@ -0,0 +1,187 @@
+//
+// Copyright (c) 2017 anygone contributors (see AUTHORS file)
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// * Neither the name of anygone nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+
+package satp
+
+import (
+ "bytes"
+ "reflect"
+ "testing"
+)
+
+func TestPlainPacketMarshal(t *testing.T) {
+ testvectors := []struct {
+ packet PlainPacket
+ valid bool
+ expected []byte
+ }{
+ {
+ PlainPacket{}, true,
+ []byte{0x0, 0x0},
+ },
+ {
+ PlainPacket{Payload: []byte{0x0, 0x0, 0x0}}, true,
+ []byte{0x0, 0x0, 0x0, 0x0, 0x0},
+ },
+ // TODO: much more test vectors
+ }
+
+ for _, vector := range testvectors {
+ result, err := vector.packet.MarshalBinary()
+ if vector.valid {
+ if err != nil {
+ t.Fatal("unexpected error:", err)
+ }
+ if bytes.Compare(vector.expected, result) != 0 {
+ t.Fatalf("resulting packet is invalid is: '%v', should be '%v'", result, vector.expected)
+ }
+ } else {
+ if err == nil {
+ t.Fatalf("marshalling '%+v' should give an error", vector.packet)
+ }
+ }
+ }
+}
+
+func TestPlainPacketUnmarshal(t *testing.T) {
+ testvectors := []struct {
+ data []byte
+ valid bool
+ expected PlainPacket
+ }{
+ {
+ []byte{},
+ false, PlainPacket{},
+ },
+ {
+ []byte{0x0},
+ false, PlainPacket{},
+ },
+ {
+ []byte{0x0, 0x0},
+ true, PlainPacket{},
+ },
+ {
+ []byte{0x0, 0x0, 0x0},
+ true, PlainPacket{Payload: []byte{0x0}},
+ },
+ {
+ []byte{0x0, 0x0, 0x0, 0x01},
+ true, PlainPacket{Payload: []byte{0x0, 0x01}},
+ },
+ // TODO: much more test vectors
+ }
+
+ for _, vector := range testvectors {
+ var result PlainPacket
+ err := result.UnmarshalBinary(vector.data)
+ if vector.valid {
+ if err != nil {
+ t.Fatal("unexpected error:", err)
+ }
+ if !reflect.DeepEqual(vector.expected, result) {
+ t.Fatalf("unmarshalled packet is wrong: is '%+v', should be '%+v'", result, vector.expected)
+ }
+ } else {
+ if err == nil {
+ t.Fatalf("unmarshalling '%+v' should give an error", vector.data)
+ }
+ }
+ }
+}
+
+func TestEncryptedPacketMarshal(t *testing.T) {
+ testvectors := []struct {
+ packet EncryptedPacket
+ valid bool
+ expected []byte
+ }{
+ {
+ EncryptedPacket{}, false,
+ []byte{},
+ },
+ {
+ EncryptedPacket{Payload: []byte{0x0, 0x0}}, true,
+ []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
+ },
+ // TODO: much more test vectors
+ }
+
+ for _, vector := range testvectors {
+ result, err := vector.packet.MarshalBinary()
+ if vector.valid {
+ if err != nil {
+ t.Fatal("unexpected error:", err)
+ }
+ if bytes.Compare(vector.expected, result) != 0 {
+ t.Fatalf("resulting packet is invalid is: '%v', should be '%v'", result, vector.expected)
+ }
+ } else {
+ if err == nil {
+ t.Fatalf("marshalling '%+v' should give an error", vector.packet)
+ }
+ }
+ }
+}
+
+func TestEncryptedPacketUnmarshal(t *testing.T) {
+ testvectors := []struct {
+ data []byte
+ valid bool
+ expected EncryptedPacket
+ }{
+ {
+ []byte{},
+ false, EncryptedPacket{},
+ },
+ {
+ []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
+ true, EncryptedPacket{Payload: []byte{0x0, 0x0}},
+ },
+ // TODO: much more test vectors
+ }
+
+ for _, vector := range testvectors {
+ var result EncryptedPacket
+ err := result.UnmarshalBinary(vector.data)
+ if vector.valid {
+ if err != nil {
+ t.Fatal("unexpected error:", err)
+ }
+ if !reflect.DeepEqual(vector.expected, result) {
+ t.Fatalf("unmarshalled packet is wrong: is '%+v', should be '%+v'", result, vector.expected)
+ }
+ } else {
+ if err == nil {
+ t.Fatalf("unmarshalling '%+v' should give an error", vector.data)
+ }
+ }
+ }
+}