Adding client algorithm; modifying some parts of server algorithm - first draft
[iotcloud.git] / doc / iotcloud.tex
1 \documentclass[11pt]{article}\r
2 \newcommand{\tuple}[1]{\ensuremath \langle #1 \rangle}\r
3 \usepackage{color}\r
4 \usepackage{amsthm}\r
5 \usepackage{algpseudocode}% http://ctan.org/pkg/algorithmicx\r
6 \newtheorem{theorem}{Theorem}\r
7 \newtheorem{defn}{Definition}\r
8 \newcommand{\note}[1]{{\color{red} \bf [[#1]]}}\r
9 \newcommand{\pushcode}[1][1]{\hskip\dimexpr #1\algorithmicindent\relax}\r
10 \begin{document}\r
11 \section{Approach}\r
12 \r
13 \subsection{Keys}\r
14 \r
15 Each device has: user id + password\r
16 \r
17 Server login is:\r
18 hash1(user id), hash1(password)\r
19 \r
20 Symmetric Crypto keys is:\r
21 hash2(user id | password)\r
22 \r
23 Server has finite length queue of entries + max\_entry\_identifier +\r
24 server login key\r
25 \r
26 \subsection{Entry layout}\r
27 Each entry has:\r
28 \begin{enumerate}\r
29 \item Sequence identifier\r
30 \item Random IV (if needed by crypto algorithm)\r
31 \item Encrypted payload\r
32 \end{enumerate}\r
33 \r
34 Payload has:\r
35 \begin{enumerate}\r
36 \item Sequence identifier\r
37 \item Machine id (most probably something like a 64-bit random number \r
38 that is self-generated by client)\r
39 \item HMAC of previous slot\r
40 \item Data entries\r
41 \item HMAC of current slot\r
42 \end{enumerate}\r
43 \r
44 A data entry can be one of these:\r
45 \begin{enumerate}\r
46 \item All or part of a Key-value entry\r
47 \item Slot sequence entry: Machine id + last message identifier \r
48 \newline {The purpose of this is to keep the record of the last slot \r
49 from a certain client if a client's update has to expunge that other \r
50 client's last entry from the queue. This is kept in the slot until \r
51 the entry owner inserts a newer update into the queue.}\r
52 \item Queue state entry: Includes queue size \newline {The purpose \r
53 of this is for the client to tell if the server lies about the number \r
54 of slots in the queue, e.g. if there are 2 queue state entry in the queue, \r
55 e.g. 50 and 70, the client knows that when it sees 50, it should expect \r
56 at most 50 slots in the queue and after it sees 70, it should expect \r
57 50 slots before that queue state entry slot 50 and at most 70 slots. \r
58 The queue state entry slot 70 is counted as slot number 51 in the queue.}\r
59 \end{enumerate}\r
60 \r
61 \subsection{Live status}\r
62 \r
63 Live status of entries:\r
64 \begin{enumerate}\r
65 \item Key-Value Entry is dead if either (a) there is a newer key-value pair or (b) it is incomplete.\r
66         \r
67 \item Slot sequence number (of either a message version data\r
68 or user-level data) is dead if there is a newer slot from the same machine.\r
69 \r
70 \item Queue state entry is dead if there is a newer queue state entry.\r
71 {In the case of queue state entries 50 and 70, this means that queue state \r
72 entry 50 is dead and 70 is live. However, not until the number of slots reaches \r
73 70 that queue state entry 50 will be expunged from the queue.}\r
74 \end{enumerate}\r
75 \r
76 When data is at the end of the queue ready to expunge, if:\r
77 \begin{enumerate}\r
78 \item The key-value entry is not dead, it must be reinserted at the\r
79 beginning of the queue.\r
80 \r
81 \item If the slot sequence number is not dead, then a message sequence\r
82 entry must be inserted.\r
83 \r
84 \item If the queue state entry is not dead, it must be reinserted at the\r
85 beginning of the queue.\r
86 \end{enumerate}\r
87 \r
88 \r
89 \paragraph{Reads:}\r
90 Client sends a sequence number.  Server replies with either: all data\r
91 entries or all newer data entries.\r
92 \r
93 \paragraph{Writes:}\r
94 Client sends slot, server verifies that sequence number is valid,\r
95 checks entry hash, and replies with an accept message if all checks\r
96 pass.  On success, client updates its sequence number.  On failure,\r
97 server sends updates slots to client and client validates those slots.\r
98 \r
99 \paragraph{Local state on each client:}\r
100 A list of machines and the corresponding latest sequence numbers.\r
101 \r
102 \paragraph{Validation procedure on client:}\r
103 \begin{enumerate}\r
104 \item Decrypt each new slot in order.\r
105 \item For each slot:\r
106     (a) check its HMAC, and\r
107     (b) check that the previous entry HMAC field matches the previous\r
108     entry.\r
109 \item Check that the last message version for our machine matches our\r
110 last message sent.\r
111 \item For all other machines, check that the latest sequence number is\r
112 at least as large (never goes backwards).\r
113 \item That the queue has a current queue state entry.\r
114 \item That the number of entries received is consistent with the size\r
115 specified in the queue state entry.\r
116 \end{enumerate}\r
117 \r
118 Key-value entries can span multiple slots.  They aren't valid until\r
119 they are complete.\r
120 \r
121 \subsection{Resizing Queue}\r
122 Client can make a request to resize the queue. This is done as a write that combines:\r
123   (a) a slot with the message, and\r
124         (b) a request to the server\r
125 \r
126 \subsection{Server Algorithm}\r
127 \begin{algorithmic}[1]\r
128 %\Function{CallServer}{$m$,$max$,$s$,$Data*$}\r
129 \Function{CallServer}{$m,max,s,Data*$}\r
130 \textit{\r
131 \newline{// m = client message (read/write/resize)}\r
132 \newline{// max = maximum number of slots (input only for resize message)}\r
133 \newline{// n = number of slots}\r
134 \newline{// s = sequence number}\r
135 \newline{// t = sequence numbers of slots on server}\r
136 \newline{// d = sequence number difference (1 by default)}\r
137 \newline{// Data = array of slots written/read (input only for write)}\r
138 \newline{// Q = queue of slots on server}\r
139 \newline{// Slot = one data slot)}\r
140 \newline{// Resize() returns the old last slot in the queue}\r
141 \newline{// Append() updates Q and latest s after appending the new slot}\r
142 \newline{// Append() returns the latest Slot written with its correct s}\r
143 }\r
144 \If{$m = read$}\r
145         \If{$s \in T = \{t_1, t_2, \dots, t_n\}$}\r
146                 \State $Data \gets \{Slot_{s}, Slot_{s+1}, \dots, Slot_{t_n}\} \forall Slot_i \in Q$\r
147         \Else\r
148                 \State $Data \gets \emptyset$\r
149         \EndIf\r
150 \ElsIf{$m = write$}\r
151         \If{$(s = t_n + d) \land (n \leq max) \land (Length(Data) = 1$)}\r
152                 \State $newSlot \gets Data[1]$\r
153                 \If{$n = max$}\r
154                         \State $Data[2] \gets RemoveFirst(Q)$\r
155                         \State $Data[1] \gets Append(newSlot,Q)$\r
156                 \Else \Comment{$n < max$}\r
157                         \State $n \gets n + 1$\r
158                         \State $Data[1] \gets Append(newSlot,Q)$\r
159                 \EndIf\r
160         \Else\r
161                 \State $Data \gets \emptyset$\r
162         \EndIf\r
163 \ElsIf{$m = resize$}\r
164         \State $Data \gets Resize(max)$\r
165 \EndIf\r
166 \State \Return{$Data$}\r
167 \EndFunction\r
168 \end{algorithmic}\r
169 \r
170 \subsection{Client Algorithm}\r
171 \begin{algorithmic}[1]\r
172 \Function{CallClient}{$uid,pw,d,m,max,s,Data*,Result*$}\r
173 \textit{\r
174 \newline{// uid = user identification}\r
175 \newline{// pw = password}\r
176 \newline{// d = new data for write}\r
177 \newline{// m = client message (read/write/resize)}\r
178 \newline{// max = maximum number of slots (input only for resize message)}\r
179 \newline{// n = number of slots}\r
180 \newline{// s = sequence number for server request}\r
181 \newline{// t = sequence numbers of slots on server}\r
182 \newline{// mid = machine identification}\r
183 \newline{// seq = sequence number inside slot}\r
184 \newline{// newSlot = new slot}\r
185 \newline{// expSlot = expunged/expired slot}\r
186 \newline{// slotSeqE = slot sequence entry}\r
187 \newline{// M = list of all machines/devices with their respective latest s on client}\r
188 \newline{// Data = array of slots written/read (input only for write)}\r
189 \newline{// Result = array of decrypted and valid slots after a read}\r
190 \newline{// Slot = one data slot)}\r
191 \newline{// DSlot = one decrypted data slot)}\r
192 }\r
193 \State $SK = Hash(uid + pw)$\r
194 \If{$m = read$}\r
195         \State $Data \gets CallServer(m,max,s,Data)$\r
196         \If{$Data = \emptyset$}\r
197                 \State $ReportError(\emptyset,read)$\r
198         \Else\r
199                 \If{$\neg HasCurrentQueueStateEntry(Data)$}\r
200                         \State $ReportError(DSlot_i,read)$\r
201                 \EndIf\r
202                 \ForAll{$Slot_i \in Data$}\r
203                         \State $DSlot_i \gets Decrypt(SK,Slot_i)$\Comment{Check s and HMAC}\r
204                         \If{$\neg (ValidSeqN(DSlot_i) \land ValidHmac(DSlot_i) \land $\\\r
205                                 \pushcode[1] $ValidPrevHmac(DSlot_i))$}\r
206                                 \State $ReportError(DSlot_i,read)$\r
207                         \Else\Comment{Check only live entries}\r
208                                 \If{$IsLiveSlotSequenceEntry(DSlot_i)$}\r
209                                         \State $lastS \gets LastSeqN(DSlot_i)$\r
210                                         \State $lastMid \gets LastMachineId(DSlot_i)$\r
211                                         \If{$lastS \neq LastSeqN(lastMid,M)$}\r
212                                                 \State $ReportError(DSlot_i,read)$\r
213                                         \EndIf\r
214                                 \ElsIf{$IsLiveKeyValueEntry(DSlot_i)$}\r
215                                         \State $mid \gets MachineId(DSlot_i)$\r
216                                         \State $seq \gets SeqN(DSlot_i)$\r
217                                         \If{$IsOwnMid(mid)$}\r
218                                                 \If{$IsLastS(mid,seq,Data) \land $\\\r
219                                                 \pushcode[1] $(seq \neq LastSeqN(mid,M))$}\r
220                                                         \State $ReportError(DSlot_i,read)$\r
221                                                 \EndIf\r
222                                         \Else\Comment{Check s for other machines}\r
223                                                 \If{$IsLastS(mid,seq,Data) \land $\\\r
224                                                 \pushcode[1] $(seq < LastSeqN(mid,M))$}\r
225                                                         \State $ReportError(DSlot_i,read)$\r
226                                                 \EndIf\r
227                                         \EndIf\Comment{Check queue state entry}\r
228                                 \ElsIf{$IsLiveQueueStateEntry(DSlot_i)$}\r
229                                         \If{$IsCurrentQueueState(DSlot_i)$}\r
230                                                 \If{$Length(Data) > QueueLength(DSlot_i)$}\r
231                                                         \State $ReportError(DSlot_i,read)$\r
232                                                 \EndIf\r
233                                         \EndIf\r
234                                 \Else\r
235                                         \State $ReportError(DSlot_i,read)$\r
236                                 \EndIf\r
237                         \EndIf\r
238                         \State $Result \gets Concat(Result, DSlot_i)$\r
239                 \EndFor\r
240         \EndIf\r
241 \r
242 \ElsIf{$m = write$}\r
243         \State $newSlot \gets CreateSlot(d)$\r
244         \State $Data[1] \gets Encrypt(SK,newSlot)$\r
245         \State $Data \gets CallServer(m,max,s,Data)$\r
246         \If{$Data = \emptyset$}\r
247                 \State $ReportError(\emptyset,write)$\r
248         \Else\Comment Check for valid return value from server\r
249                 \If{$\neg ValidOldLastEntry(Data[1])$}\r
250                         \State $ReportError(Data[1],write)$\r
251                 \Else\Comment{Check if we need slot sequence entry}\r
252                         \If{$Length(Data) = 2$}\r
253                                 \State $expSlot \gets Decrypt(SK,Data[2])$\r
254                                 \State $mid \gets MachineId(expSlot)$\r
255                                 \State $seq \gets SeqN(expSlot)$\r
256                                 \If{$seq = LastSeqN(mid,M)$}\Comment{Liveness check}\r
257                                         \State $slotSeqE \gets CreateSlotSeqE(mid,seq)$\r
258                                         \State $Data[1] \gets Encrypt(SK,slotSeqE)$\r
259                                         \State $Data \gets CallServer(m,max,s,Data)$\r
260                                 \EndIf\r
261                         \Else\r
262                                 \State $ReportError(Data,write)$\r
263                         \EndIf\r
264                 \EndIf\r
265         \EndIf\r
266 \r
267 \ElsIf{$m = resize$}\r
268         \State $Data \gets CallServer(m,max,s,Data)$\r
269         \If{$Data = \emptyset$}\r
270                 \State $ReportError(\emptyset,resize)$\r
271         \EndIf\r
272 \EndIf\r
273 \State \Return{$Result$}\r
274 \EndFunction\r
275 \end{algorithmic}\r
276 \r
277 \subsection{Formal Guarantees}\r
278 \r
279 \textit{To be completed ...}\r
280 \r
281 \begin{defn}[System Execution]\r
282 Formalize a system execution as a sequence of slot updates...  There\r
283 is a total order of all slot updates.\r
284 \end{defn}\r
285 \r
286 \begin{defn}[Transitive Closure]\r
287 Define transitive closure relation for slot updates...  There is an\r
288 edge from a slot update to a slot receive event if the receive event\r
289 reads from the update event.\r
290 \end{defn}\r
291 \r
292 \begin{defn}[Suborder]\r
293 Define suborder of total order.  It is a sequence of contiguous slots\r
294 updates (as observed by a given device).\r
295 \end{defn}\r
296 \r
297 \begin{defn}[Prefix of a suborder]\r
298 Given a sub order $o=u_{i},u_{i+1},...,u_j, u_{j+i},..., u', ...$ and\r
299 a slot update $u'$ in $o$, the prefix of $o$ is a sequence of all\r
300 updates that occur before $u'$ and $u'$.\r
301 \end{defn}\r
302 \r
303 \begin{defn}[Consistency between a suborder and a total order]\r
304 A suborder $o$ is consistent with a total order $t$, if all updates in $o$ appear in $t$ and they appear in the same order.\r
305 \end{defn}\r
306 \r
307 \begin{defn}[Consistency between suborders]\r
308 Define notion of consistency between suborders...  Two suborders U,V\r
309 are consistent if there exist a total order T such that both U and V\r
310 are suborders of T.\r
311 \end{defn}\r
312 \r
313 \begin{defn}[Error-free execution]\r
314 Define error-free execution --- execution for which the client does\r
315 not flag any errors...\r
316 \end{defn}\r
317 \r
318 \begin{theorem} Error-free execution of algorithm ensures that the suborder\r
319 for node n is consistent with the prefix suborder for all other nodes\r
320 that are in the transitive closure.\r
321 \end{theorem}\r
322 \begin{proof}\r
323 \textit{TODO}\r
324 \end{proof}\r
325 \r
326 \begin{defn}[State of Data Structure]\r
327 Define in terms of playing all updates sequentially onto local data\r
328 structure.\r
329 \end{defn}\r
330 \r
331 \begin{theorem}\r
332 Algorithm gives consistent view of data structure.\r
333 \end{theorem}\r
334 \begin{proof}\r
335 \textit{TODO}\r
336 \end{proof}\r
337 \r
338 \subsection{Future Work}\r
339 \paragraph{Support Messages}\r
340   A message is dead once receiving machine sends an entry with a newer\r
341   sequence identifier\r
342 \r
343 \paragraph{Persistent data structures}\r
344         Root object w/ fields\r
345         Other objects can be reachable from root\r
346         Each object has its own entries\r
347         Dead objects correspond to dead \r
348 \r
349 \paragraph{Multiple App Sharing}\r
350 \r
351 Idea is to separate subspace of entries...  Shared with other cloud...\r
352 \end{document}\r