more code
[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 {
8         public static final int SLOT_SIZE=2048;
9         public 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
17         Slot(long _seqnum, long _machineid, byte[] _prevhmac, byte[] _hmac, Vector<Entry> _entries) {
18                 seqnum=_seqnum;
19                 machineid=_machineid;
20                 prevhmac=_prevhmac;
21                 hmac=_hmac;
22                 entries=_entries;
23         }
24         
25         Slot(long _seqnum, byte[] _bytes) {
26                 seqnum=_seqnum;
27         }
28
29         byte[] getHMAC() {
30                 return hmac;
31         }
32
33         byte[] getPrevHMAC() {
34                 return prevhmac;
35         }
36
37         Vector<Entry> getEntries() {
38                 return entries;
39         }
40         
41         static Slot decode(byte[] array, Mac mac) {
42                 mac.update(array, HMAC_SIZE, array.length-HMAC_SIZE);
43                 byte[] realmac=mac.doFinal();
44
45                 ByteBuffer bb=ByteBuffer.wrap(array);
46                 byte[] hmac=new byte[HMAC_SIZE];
47                 byte[] prevhmac=new byte[HMAC_SIZE];
48                 bb.get(hmac);
49                 bb.get(prevhmac);
50                 if (!Arrays.equals(realmac, hmac))
51                         throw new Error("Server Error: Invalid HMAC!  Potential Attack!");
52
53                 long seqnum=bb.getLong();
54                 long machineid=bb.getLong();
55                 int numentries=bb.getInt();
56                 Vector<Entry> entries=new Vector<Entry>();
57                 for(int i=0;i<numentries;i++) {
58                         entries.add(Entry.decode(bb));
59                 }
60                 
61                 return new Slot(seqnum, machineid, prevhmac, hmac, entries);
62         }
63
64         byte[] encode(Mac mac) {
65                 byte[] array=new byte[SLOT_SIZE];
66                 ByteBuffer bb=ByteBuffer.wrap(array);
67                 bb.position(HMAC_SIZE); //Leave space for the HMACs
68                 bb.put(prevhmac);
69                 bb.putLong(seqnum);
70                 bb.putLong(machineid);
71                 bb.putInt(entries.size());
72                 for(Entry entry:entries) {
73                         entry.encode(bb);
74                 }
75                 //Compute our HMAC
76                 mac.update(array, HMAC_SIZE, array.length-HMAC_SIZE);
77                 byte[] realmac=mac.doFinal();
78                 bb.position(0);
79                 bb.put(realmac);
80                 return array;
81         }
82         
83         long getSequenceNumber() {
84                 return seqnum;
85         }
86
87         byte[] getBytes() {
88                 return null;
89         }
90         
91         public String toString() {
92                 return "<"+getSequenceNumber()+", "+new String(getBytes())+">";
93         }
94 }