045259015c59d3f2a280300e81ca7031ddf7c476
[iotcloud.git] / src / java / iotcloud / Slot.java
1 package iotcloud;
2 import java.util.Vector;
3 import java.nio.ByteBuffer;
4 import javax.crypto.Mac;
5 import java.util.Arrays;
6
7 class Slot implements Liveness {
8         static final int SLOT_SIZE=2048;
9         static final int HMAC_SIZE=32;
10
11         private long seqnum;
12         private byte[] prevhmac;
13         private byte[] hmac;
14         private long machineid;
15         private Vector<Entry> entries;
16         private int livecount;
17         
18         Slot(long _seqnum, long _machineid, byte[] _prevhmac, byte[] _hmac) {
19                 seqnum=_seqnum;
20                 machineid=_machineid;
21                 prevhmac=_prevhmac;
22                 hmac=_hmac;
23                 entries=new Vector<Entry>();
24                 livecount=1;
25         }
26         
27         Slot(long _seqnum, byte[] _bytes) {
28                 seqnum=_seqnum;
29         }
30
31         byte[] getHMAC() {
32                 return hmac;
33         }
34
35         byte[] getPrevHMAC() {
36                 return prevhmac;
37         }
38
39         void addEntry(Entry e) {
40                 entries.add(e);
41                 livecount++;
42         }
43         
44         Vector<Entry> getEntries() {
45                 return entries;
46         }
47         
48         static Slot decode(byte[] array, Mac mac) {
49                 mac.update(array, HMAC_SIZE, array.length-HMAC_SIZE);
50                 byte[] realmac=mac.doFinal();
51
52                 ByteBuffer bb=ByteBuffer.wrap(array);
53                 byte[] hmac=new byte[HMAC_SIZE];
54                 byte[] prevhmac=new byte[HMAC_SIZE];
55                 bb.get(hmac);
56                 bb.get(prevhmac);
57                 if (!Arrays.equals(realmac, hmac))
58                         throw new Error("Server Error: Invalid HMAC!  Potential Attack!");
59
60                 long seqnum=bb.getLong();
61                 long machineid=bb.getLong();
62                 int numentries=bb.getInt();
63                 Slot slot=new Slot(seqnum, machineid, prevhmac, hmac);
64                 
65                 for(int i=0;i<numentries;i++) {
66                         slot.addEntry(Entry.decode(slot, bb));
67                 }
68                 
69                 return slot;
70         }
71
72         byte[] encode(Mac mac) {
73                 byte[] array=new byte[SLOT_SIZE];
74                 ByteBuffer bb=ByteBuffer.wrap(array);
75                 bb.position(HMAC_SIZE); //Leave space for the HMACs
76                 bb.put(prevhmac);
77                 bb.putLong(seqnum);
78                 bb.putLong(machineid);
79                 bb.putInt(entries.size());
80                 for(Entry entry:entries) {
81                         entry.encode(bb);
82                 }
83                 //Compute our HMAC
84                 mac.update(array, HMAC_SIZE, array.length-HMAC_SIZE);
85                 byte[] realmac=mac.doFinal();
86                 bb.position(0);
87                 bb.put(realmac);
88                 return array;
89         }
90         
91         long getSequenceNumber() {
92                 return seqnum;
93         }
94
95         long getMachineID() {
96                 return machineid;
97         }
98         
99         byte[] getBytes() {
100                 return null;
101         }
102
103         void decrementLiveCount() {
104                 livecount--;
105         }
106         
107         boolean isLive() {
108                 return livecount > 0;
109         }
110
111         public String toString() {
112                 return "<"+getSequenceNumber()+", "+new String(getBytes())+">";
113         }
114 }