aboutsummaryrefslogtreecommitdiff
path: root/inform/codec.go
blob: e74c3d74d4a54a3d66ee81d3d767205eee898ba0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
package inform

import (
	"bytes"
	"encoding/binary"
	"errors"
	"io"
)

type Codec struct {
	// KeyBag contains a mapping of comma-separated MAC addresses to their AES
	// keys
	KeyBag map[string]string
}

func (c *Codec) Unmarshal(fp io.Reader) (*InformWrapper, error) {
	w := NewInformWrapper()

	var magic int32
	binary.Read(fp, binary.BigEndian, &magic)
	if magic != PROTOCOL_MAGIC {
		return nil, errors.New("Invalid magic number")
	}

	binary.Read(fp, binary.BigEndian, &w.Version)
	io.ReadFull(fp, w.MacAddr)
	binary.Read(fp, binary.BigEndian, &w.Flags)

	iv := make([]byte, 16)
	io.ReadFull(fp, iv)

	binary.Read(fp, binary.BigEndian, &w.DataVersion)

	var dataLen int32
	binary.Read(fp, binary.BigEndian, &dataLen)

	p := make([]byte, dataLen)
	io.ReadFull(fp, p)

	key, ok := c.KeyBag[w.FormattedMac()]
	if !ok {
		return nil, errors.New("No key found")
	}

	u, err := Decrypt(p, iv, key)
	if err != nil {
		return nil, err
	}

	w.Payload = u

	return w, nil
}

func (c *Codec) Marshal(msg *InformWrapper) ([]byte, error) {
	b := &bytes.Buffer{}
	payload := msg.Payload
	var iv []byte

	if msg.IsEncrypted() {
		key, ok := c.KeyBag[msg.FormattedMac()]
		if !ok {
			return nil, errors.New("No key found")
		}

		var err error
		payload, iv, err = Encrypt(payload, key)
		if err != nil {
			return nil, err
		}
	}

	binary.Write(b, binary.BigEndian, PROTOCOL_MAGIC)
	binary.Write(b, binary.BigEndian, msg.Version)
	b.Write(msg.MacAddr)
	binary.Write(b, binary.BigEndian, msg.Flags)
	b.Write(iv)
	binary.Write(b, binary.BigEndian, msg.DataVersion)
	binary.Write(b, binary.BigEndian, int32(len(payload)))
	b.Write(payload)

	return b.Bytes(), nil
}