2 import java.util.Vector;
3 import java.nio.ByteBuffer;
4 import javax.crypto.Mac;
5 import java.util.Arrays;
7 class Slot implements Liveness {
8 static final int SLOT_SIZE=2048;
9 static final int HMAC_SIZE=32;
12 private byte[] prevhmac;
14 private long machineid;
15 private Vector<Entry> entries;
16 private int livecount;
17 private boolean seqnumlive;
19 Slot(long _seqnum, long _machineid, byte[] _prevhmac, byte[] _hmac) {
24 entries=new Vector<Entry>();
29 Slot(long _seqnum, long _machineid, byte[] _prevhmac) {
30 this(_seqnum, _machineid, _prevhmac, new byte[HMAC_SIZE]);
37 byte[] getPrevHMAC() {
41 void addEntry(Entry e) {
46 Vector<Entry> getEntries() {
50 static Slot decode(byte[] array, Mac mac) {
51 mac.update(array, HMAC_SIZE, array.length-HMAC_SIZE);
52 byte[] realmac=mac.doFinal();
54 ByteBuffer bb=ByteBuffer.wrap(array);
55 byte[] hmac=new byte[HMAC_SIZE];
56 byte[] prevhmac=new byte[HMAC_SIZE];
59 if (!Arrays.equals(realmac, hmac))
60 throw new Error("Server Error: Invalid HMAC! Potential Attack!");
62 long seqnum=bb.getLong();
63 long machineid=bb.getLong();
64 int numentries=bb.getInt();
65 Slot slot=new Slot(seqnum, machineid, prevhmac, hmac);
67 for(int i=0; i<numentries; i++) {
68 slot.addEntry(Entry.decode(slot, bb));
74 byte[] encode(Mac mac) {
75 byte[] array=new byte[SLOT_SIZE];
76 ByteBuffer bb=ByteBuffer.wrap(array);
77 bb.position(HMAC_SIZE); //Leave space for the HMACs
80 bb.putLong(machineid);
81 bb.putInt(entries.size());
82 for(Entry entry:entries) {
86 mac.update(array, HMAC_SIZE, array.length-HMAC_SIZE);
87 byte[] realmac=mac.doFinal();
93 long getSequenceNumber() {
106 decrementLiveCount();
110 void decrementLiveCount() {
115 return livecount > 0;
118 public String toString() {
119 return "<"+getSequenceNumber()+", "+new String(getBytes())+">";