package iotcloud;
import java.util.Vector;
+import java.nio.ByteBuffer;
+import javax.crypto.Mac;
+import java.util.Arrays;
class Slot {
- long seqnum;
- byte[] bytes;
- Vector<Entry> entries;
+ public static final int SLOT_SIZE=2048;
+ public static final int HMAC_SIZE=32;
- Slot() {
- entries=new Vector();
+ private long seqnum;
+ private byte[] prevhmac;
+ private byte[] hmac;
+ private long machineid;
+ private Vector<Entry> entries;
+
+ Slot(long _seqnum, long _machineid, byte[] _prevhmac, byte[] _hmac, Vector<Entry> _entries) {
+ seqnum=_seqnum;
+ machineid=_machineid;
+ prevhmac=_prevhmac;
+ hmac=_hmac;
+ entries=_entries;
}
Slot(long _seqnum, byte[] _bytes) {
- this();
seqnum=_seqnum;
- bytes=_bytes;
+ }
+
+ byte[] getHMAC() {
+ return hmac;
+ }
+
+ byte[] getPrevHMAC() {
+ return prevhmac;
+ }
+
+ Vector<Entry> getEntries() {
+ return entries;
+ }
+
+ static Slot decode(byte[] array, Mac mac) {
+ mac.update(array, HMAC_SIZE, array.length-HMAC_SIZE);
+ byte[] realmac=mac.doFinal();
+
+ ByteBuffer bb=ByteBuffer.wrap(array);
+ byte[] hmac=new byte[HMAC_SIZE];
+ byte[] prevhmac=new byte[HMAC_SIZE];
+ bb.get(hmac);
+ bb.get(prevhmac);
+ if (!Arrays.equals(realmac, hmac))
+ throw new Error("Server Error: Invalid HMAC! Potential Attack!");
+
+ long seqnum=bb.getLong();
+ long machineid=bb.getLong();
+ int numentries=bb.getInt();
+ Vector<Entry> entries=new Vector<Entry>();
+ for(int i=0;i<numentries;i++) {
+ entries.add(Entry.decode(bb));
+ }
+
+ return new Slot(seqnum, machineid, prevhmac, hmac, entries);
+ }
+
+ byte[] encode(Mac mac) {
+ byte[] array=new byte[SLOT_SIZE];
+ ByteBuffer bb=ByteBuffer.wrap(array);
+ bb.position(HMAC_SIZE); //Leave space for the HMACs
+ bb.put(prevhmac);
+ bb.putLong(seqnum);
+ bb.putLong(machineid);
+ bb.putInt(entries.size());
+ for(Entry entry:entries) {
+ entry.encode(bb);
+ }
+ //Compute our HMAC
+ mac.update(array, HMAC_SIZE, array.length-HMAC_SIZE);
+ byte[] realmac=mac.doFinal();
+ bb.position(0);
+ bb.put(realmac);
+ return array;
}
long getSequenceNumber() {
return seqnum;
}
+ long getMachineID() {
+ return machineid;
+ }
+
byte[] getBytes() {
- return bytes;
+ return null;
}
public String toString() {