1 // Copyright 2015 The Weave Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/macaroon_caveat.h"
6 #include "src/macaroon_caveat_internal.h"
7 
8 #include <string.h>
9 
10 #include "src/crypto_hmac.h"
11 #include "src/macaroon.h"
12 #include "src/macaroon_context.h"
13 #include "src/macaroon_encoding.h"
14 
is_valid_caveat_type_(UwMacaroonCaveatType type)15 static bool is_valid_caveat_type_(UwMacaroonCaveatType type) {
16   switch (type) {
17     case kUwMacaroonCaveatTypeNonce:
18     case kUwMacaroonCaveatTypeScope:
19     case kUwMacaroonCaveatTypeExpirationAbsolute:
20     case kUwMacaroonCaveatTypeTTL1Hour:
21     case kUwMacaroonCaveatTypeTTL24Hour:
22     case kUwMacaroonCaveatTypeDelegationTimestamp:
23     case kUwMacaroonCaveatTypeDelegateeUser:
24     case kUwMacaroonCaveatTypeDelegateeApp:
25     case kUwMacaroonCaveatTypeAppCommandsOnly:
26     case kUwMacaroonCaveatTypeDelegateeService:
27     case kUwMacaroonCaveatTypeBleSessionID:
28     case kUwMacaroonCaveatTypeLanSessionID:
29     case kUwMacaroonCaveatTypeClientAuthorizationTokenV1:
30     case kUwMacaroonCaveatTypeServerAuthenticationTokenV1:
31       return true;
32   }
33   return false;
34 }
35 
is_valid_scope_type_(UwMacaroonCaveatScopeType type)36 static bool is_valid_scope_type_(UwMacaroonCaveatScopeType type) {
37   switch (type) {
38     case kUwMacaroonCaveatScopeTypeOwner:
39     case kUwMacaroonCaveatScopeTypeManager:
40     case kUwMacaroonCaveatScopeTypeUser:
41     case kUwMacaroonCaveatScopeTypeViewer:
42       return true;
43   }
44   return false;
45 }
46 
create_caveat_no_value_(UwMacaroonCaveatType type,uint8_t * buffer,size_t buffer_size,UwMacaroonCaveat * new_caveat)47 static bool create_caveat_no_value_(UwMacaroonCaveatType type,
48                                     uint8_t* buffer,
49                                     size_t buffer_size,
50                                     UwMacaroonCaveat* new_caveat) {
51   // (buffer_size == 0 || get_buffer_size_() > buffer_size) will conver the case
52   // that get_buffer_size_() returns 0 (for errors), so there is no need to
53   // check get_buffer_size_() == 0 again.
54   if (buffer == NULL || buffer_size == 0 || new_caveat == NULL ||
55       uw_macaroon_caveat_creation_get_buffsize_(type, 0) > buffer_size) {
56     return false;
57   }
58 
59   size_t encoded_str_len = 0, total_str_len = 0;
60   if (!uw_macaroon_encoding_encode_uint_((uint32_t)type, buffer, buffer_size,
61                                          &encoded_str_len)) {
62     return false;
63   }
64   total_str_len += encoded_str_len;
65 
66   new_caveat->bytes = buffer;
67   new_caveat->num_bytes = total_str_len;
68   return true;
69 }
70 
create_caveat_uint_value_(UwMacaroonCaveatType type,uint32_t unsigned_int,uint8_t * buffer,size_t buffer_size,UwMacaroonCaveat * new_caveat)71 static bool create_caveat_uint_value_(UwMacaroonCaveatType type,
72                                       uint32_t unsigned_int,
73                                       uint8_t* buffer,
74                                       size_t buffer_size,
75                                       UwMacaroonCaveat* new_caveat) {
76   if (buffer == NULL || buffer_size == 0 || new_caveat == NULL ||
77       uw_macaroon_caveat_creation_get_buffsize_(type, 0) > buffer_size) {
78     return false;
79   }
80 
81   size_t encoded_str_len = 0, total_str_len = 0;
82   if (!uw_macaroon_encoding_encode_uint_((uint32_t)type, buffer, buffer_size,
83                                          &encoded_str_len)) {
84     return false;
85   }
86   total_str_len += encoded_str_len;
87   if (!uw_macaroon_encoding_encode_uint_(unsigned_int, buffer + total_str_len,
88                                          buffer_size - total_str_len,
89                                          &encoded_str_len)) {
90     return false;
91   }
92   total_str_len += encoded_str_len;
93 
94   new_caveat->bytes = buffer;
95   new_caveat->num_bytes = total_str_len;
96   return true;
97 }
98 
create_caveat_bstr_value_(UwMacaroonCaveatType type,const uint8_t * str,size_t str_len,uint8_t * buffer,size_t buffer_size,UwMacaroonCaveat * new_caveat)99 static bool create_caveat_bstr_value_(UwMacaroonCaveatType type,
100                                       const uint8_t* str,
101                                       size_t str_len,
102                                       uint8_t* buffer,
103                                       size_t buffer_size,
104                                       UwMacaroonCaveat* new_caveat) {
105   if ((str == NULL && str_len != 0) || buffer == NULL || buffer_size == 0 ||
106       new_caveat == NULL ||
107       uw_macaroon_caveat_creation_get_buffsize_(type, str_len) > buffer_size) {
108     return false;
109   }
110 
111   size_t encoded_str_len = 0, total_str_len = 0;
112   if (!uw_macaroon_encoding_encode_uint_((uint32_t)type, buffer, buffer_size,
113                                          &encoded_str_len)) {
114     return false;
115   }
116   total_str_len += encoded_str_len;
117   if (!uw_macaroon_encoding_encode_byte_str_(
118           str, str_len, buffer + total_str_len, buffer_size - total_str_len,
119           &encoded_str_len)) {
120     return false;
121   }
122   total_str_len += encoded_str_len;
123 
124   new_caveat->bytes = buffer;
125   new_caveat->num_bytes = total_str_len;
126   return true;
127 }
128 
uw_macaroon_caveat_creation_get_buffsize_(UwMacaroonCaveatType type,size_t str_len)129 size_t uw_macaroon_caveat_creation_get_buffsize_(UwMacaroonCaveatType type,
130                                                  size_t str_len) {
131   switch (type) {
132     // No values
133     case kUwMacaroonCaveatTypeTTL1Hour:
134     case kUwMacaroonCaveatTypeTTL24Hour:
135     case kUwMacaroonCaveatTypeAppCommandsOnly:
136     case kUwMacaroonCaveatTypeBleSessionID:
137       return UW_MACAROON_ENCODING_MAX_UINT_CBOR_LEN;
138 
139     // Unsigned integers
140     case kUwMacaroonCaveatTypeScope:
141     case kUwMacaroonCaveatTypeExpirationAbsolute:
142     case kUwMacaroonCaveatTypeDelegationTimestamp:
143       return 2 * UW_MACAROON_ENCODING_MAX_UINT_CBOR_LEN;
144 
145     // Byte strings
146     case kUwMacaroonCaveatTypeNonce:
147     case kUwMacaroonCaveatTypeDelegateeUser:
148     case kUwMacaroonCaveatTypeDelegateeApp:
149     case kUwMacaroonCaveatTypeDelegateeService:
150     case kUwMacaroonCaveatTypeLanSessionID:
151     case kUwMacaroonCaveatTypeClientAuthorizationTokenV1:
152     case kUwMacaroonCaveatTypeServerAuthenticationTokenV1:
153       return str_len + UW_MACAROON_ENCODING_MAX_UINT_CBOR_LEN;
154 
155     default:
156       return 0;  // For errors
157   }
158 }
159 
uw_macaroon_caveat_create_nonce_(const uint8_t * nonce,size_t nonce_size,uint8_t * buffer,size_t buffer_size,UwMacaroonCaveat * new_caveat)160 bool uw_macaroon_caveat_create_nonce_(const uint8_t* nonce,
161                                       size_t nonce_size,
162                                       uint8_t* buffer,
163                                       size_t buffer_size,
164                                       UwMacaroonCaveat* new_caveat) {
165   return create_caveat_bstr_value_(kUwMacaroonCaveatTypeNonce, nonce,
166                                    nonce_size, buffer, buffer_size, new_caveat);
167 }
168 
uw_macaroon_caveat_create_scope_(UwMacaroonCaveatScopeType scope,uint8_t * buffer,size_t buffer_size,UwMacaroonCaveat * new_caveat)169 bool uw_macaroon_caveat_create_scope_(UwMacaroonCaveatScopeType scope,
170                                       uint8_t* buffer,
171                                       size_t buffer_size,
172                                       UwMacaroonCaveat* new_caveat) {
173   if (!is_valid_scope_type_(scope)) {
174     return false;
175   }
176 
177   return create_caveat_uint_value_(kUwMacaroonCaveatTypeScope, scope, buffer,
178                                    buffer_size, new_caveat);
179 }
180 
uw_macaroon_caveat_create_expiration_absolute_(uint32_t expiration_time,uint8_t * buffer,size_t buffer_size,UwMacaroonCaveat * new_caveat)181 bool uw_macaroon_caveat_create_expiration_absolute_(
182     uint32_t expiration_time,
183     uint8_t* buffer,
184     size_t buffer_size,
185     UwMacaroonCaveat* new_caveat) {
186   return create_caveat_uint_value_(kUwMacaroonCaveatTypeExpirationAbsolute,
187                                    expiration_time, buffer, buffer_size,
188                                    new_caveat);
189 }
190 
uw_macaroon_caveat_create_ttl_1_hour_(uint8_t * buffer,size_t buffer_size,UwMacaroonCaveat * new_caveat)191 bool uw_macaroon_caveat_create_ttl_1_hour_(uint8_t* buffer,
192                                            size_t buffer_size,
193                                            UwMacaroonCaveat* new_caveat) {
194   return create_caveat_no_value_(kUwMacaroonCaveatTypeTTL1Hour, buffer,
195                                  buffer_size, new_caveat);
196 }
197 
uw_macaroon_caveat_create_ttl_24_hour_(uint8_t * buffer,size_t buffer_size,UwMacaroonCaveat * new_caveat)198 bool uw_macaroon_caveat_create_ttl_24_hour_(uint8_t* buffer,
199                                             size_t buffer_size,
200                                             UwMacaroonCaveat* new_caveat) {
201   return create_caveat_no_value_(kUwMacaroonCaveatTypeTTL24Hour, buffer,
202                                  buffer_size, new_caveat);
203 }
204 
uw_macaroon_caveat_create_delegation_timestamp_(uint32_t timestamp,uint8_t * buffer,size_t buffer_size,UwMacaroonCaveat * new_caveat)205 bool uw_macaroon_caveat_create_delegation_timestamp_(
206     uint32_t timestamp,
207     uint8_t* buffer,
208     size_t buffer_size,
209     UwMacaroonCaveat* new_caveat) {
210   return create_caveat_uint_value_(kUwMacaroonCaveatTypeDelegationTimestamp,
211                                    timestamp, buffer, buffer_size, new_caveat);
212 }
213 
uw_macaroon_caveat_create_delegatee_user_(const uint8_t * id_str,size_t id_str_len,uint8_t * buffer,size_t buffer_size,UwMacaroonCaveat * new_caveat)214 bool uw_macaroon_caveat_create_delegatee_user_(const uint8_t* id_str,
215                                                size_t id_str_len,
216                                                uint8_t* buffer,
217                                                size_t buffer_size,
218                                                UwMacaroonCaveat* new_caveat) {
219   return create_caveat_bstr_value_(kUwMacaroonCaveatTypeDelegateeUser, id_str,
220                                    id_str_len, buffer, buffer_size, new_caveat);
221 }
222 
uw_macaroon_caveat_create_delegatee_app_(const uint8_t * id_str,size_t id_str_len,uint8_t * buffer,size_t buffer_size,UwMacaroonCaveat * new_caveat)223 bool uw_macaroon_caveat_create_delegatee_app_(const uint8_t* id_str,
224                                               size_t id_str_len,
225                                               uint8_t* buffer,
226                                               size_t buffer_size,
227                                               UwMacaroonCaveat* new_caveat) {
228   return create_caveat_bstr_value_(kUwMacaroonCaveatTypeDelegateeApp, id_str,
229                                    id_str_len, buffer, buffer_size, new_caveat);
230 }
231 
uw_macaroon_caveat_create_app_commands_only_(uint8_t * buffer,size_t buffer_size,UwMacaroonCaveat * new_caveat)232 bool uw_macaroon_caveat_create_app_commands_only_(
233     uint8_t* buffer,
234     size_t buffer_size,
235     UwMacaroonCaveat* new_caveat) {
236   return create_caveat_no_value_(kUwMacaroonCaveatTypeAppCommandsOnly, buffer,
237                                  buffer_size, new_caveat);
238 }
239 
uw_macaroon_caveat_create_delegatee_service_(const uint8_t * id_str,size_t id_str_len,uint8_t * buffer,size_t buffer_size,UwMacaroonCaveat * new_caveat)240 bool uw_macaroon_caveat_create_delegatee_service_(
241     const uint8_t* id_str,
242     size_t id_str_len,
243     uint8_t* buffer,
244     size_t buffer_size,
245     UwMacaroonCaveat* new_caveat) {
246   return create_caveat_bstr_value_(kUwMacaroonCaveatTypeDelegateeService,
247                                    id_str, id_str_len, buffer, buffer_size,
248                                    new_caveat);
249 }
250 
uw_macaroon_caveat_create_ble_session_id_(uint8_t * buffer,size_t buffer_size,UwMacaroonCaveat * new_caveat)251 bool uw_macaroon_caveat_create_ble_session_id_(uint8_t* buffer,
252                                                size_t buffer_size,
253                                                UwMacaroonCaveat* new_caveat) {
254   return create_caveat_no_value_(kUwMacaroonCaveatTypeBleSessionID, buffer,
255                                  buffer_size, new_caveat);
256 }
257 
uw_macaroon_caveat_create_lan_session_id_(const uint8_t * session_id,size_t session_id_len,uint8_t * buffer,size_t buffer_size,UwMacaroonCaveat * new_caveat)258 bool uw_macaroon_caveat_create_lan_session_id_(const uint8_t* session_id,
259                                                size_t session_id_len,
260                                                uint8_t* buffer,
261                                                size_t buffer_size,
262                                                UwMacaroonCaveat* new_caveat) {
263   return create_caveat_bstr_value_(kUwMacaroonCaveatTypeLanSessionID,
264                                    session_id, session_id_len, buffer,
265                                    buffer_size, new_caveat);
266 }
267 
uw_macaroon_caveat_create_client_authorization_token_(const uint8_t * str,size_t str_len,uint8_t * buffer,size_t buffer_size,UwMacaroonCaveat * new_caveat)268 bool uw_macaroon_caveat_create_client_authorization_token_(
269     const uint8_t* str,
270     size_t str_len,
271     uint8_t* buffer,
272     size_t buffer_size,
273     UwMacaroonCaveat* new_caveat) {
274   if (str_len == 0) {
275     return create_caveat_no_value_(
276         kUwMacaroonCaveatTypeClientAuthorizationTokenV1, buffer, buffer_size,
277         new_caveat);
278   }
279   return create_caveat_bstr_value_(
280       kUwMacaroonCaveatTypeClientAuthorizationTokenV1, str, str_len, buffer,
281       buffer_size, new_caveat);
282 }
283 
uw_macaroon_caveat_create_server_authentication_token_(const uint8_t * str,size_t str_len,uint8_t * buffer,size_t buffer_size,UwMacaroonCaveat * new_caveat)284 bool uw_macaroon_caveat_create_server_authentication_token_(
285     const uint8_t* str,
286     size_t str_len,
287     uint8_t* buffer,
288     size_t buffer_size,
289     UwMacaroonCaveat* new_caveat) {
290   if (str_len == 0) {
291     return create_caveat_no_value_(
292         kUwMacaroonCaveatTypeServerAuthenticationTokenV1, buffer, buffer_size,
293         new_caveat);
294   }
295   return create_caveat_bstr_value_(
296       kUwMacaroonCaveatTypeServerAuthenticationTokenV1, str, str_len, buffer,
297       buffer_size, new_caveat);
298 }
299 
uw_macaroon_caveat_get_type_(const UwMacaroonCaveat * caveat,UwMacaroonCaveatType * type)300 bool uw_macaroon_caveat_get_type_(const UwMacaroonCaveat* caveat,
301                                   UwMacaroonCaveatType* type) {
302   if (caveat == NULL || type == NULL) {
303     return false;
304   }
305 
306   uint32_t unsigned_int;
307   if (!uw_macaroon_encoding_decode_uint_(caveat->bytes, caveat->num_bytes,
308                                          &unsigned_int)) {
309     return false;
310   }
311 
312   *type = (UwMacaroonCaveatType)unsigned_int;
313   return is_valid_caveat_type_(*type);
314 }
315 
316 /* === Some internal functions defined in macaroon_caveat_internal.h === */
317 
uw_macaroon_caveat_sign_(const uint8_t * key,size_t key_len,const UwMacaroonContext * context,const UwMacaroonCaveat * caveat,uint8_t * mac_tag,size_t mac_tag_size)318 bool uw_macaroon_caveat_sign_(const uint8_t* key,
319                               size_t key_len,
320                               const UwMacaroonContext* context,
321                               const UwMacaroonCaveat* caveat,
322                               uint8_t* mac_tag,
323                               size_t mac_tag_size) {
324   if (key == NULL || key_len == 0 || context == NULL || caveat == NULL ||
325       mac_tag == NULL || mac_tag_size == 0) {
326     return false;
327   }
328 
329   UwMacaroonCaveatType caveat_type;
330   if (!uw_macaroon_caveat_get_type_(caveat, &caveat_type) ||
331       !is_valid_caveat_type_(caveat_type)) {
332     return false;
333   }
334 
335   // Need to encode the whole caveat as a byte string and then sign it
336 
337   // If there is no additional value from the context, just compute the HMAC on
338   // the current byte string.
339   uint8_t bstr_cbor_prefix[UW_MACAROON_ENCODING_MAX_UINT_CBOR_LEN] = {0};
340   size_t bstr_cbor_prefix_len = 0;
341   if (caveat_type != kUwMacaroonCaveatTypeBleSessionID) {
342     if (!uw_macaroon_encoding_encode_byte_str_len_(
343             (uint32_t)(caveat->num_bytes), bstr_cbor_prefix,
344             sizeof(bstr_cbor_prefix), &bstr_cbor_prefix_len)) {
345       return false;
346     }
347 
348     UwCryptoHmacMsg messages[] = {
349         {bstr_cbor_prefix, bstr_cbor_prefix_len},
350         {caveat->bytes, caveat->num_bytes},
351     };
352 
353     return uw_crypto_hmac_(key, key_len, messages,
354                            sizeof(messages) / sizeof(messages[0]), mac_tag,
355                            mac_tag_size);
356   }
357 
358   // If there is additional value from the context.
359   if (context->ble_session_id == NULL || context->ble_session_id_len == 0) {
360     return false;
361   }
362 
363   // The length here includes the length of the BLE session ID string.
364   if (!uw_macaroon_encoding_encode_byte_str_len_(
365           (uint32_t)(context->ble_session_id_len + caveat->num_bytes),
366           bstr_cbor_prefix, sizeof(bstr_cbor_prefix), &bstr_cbor_prefix_len)) {
367     return false;
368   }
369 
370   uint8_t value_cbor_prefix[UW_MACAROON_ENCODING_MAX_UINT_CBOR_LEN] = {0};
371   size_t value_cbor_prefix_len = 0;
372   if (!uw_macaroon_encoding_encode_byte_str_len_(
373           (uint32_t)(context->ble_session_id_len), value_cbor_prefix,
374           sizeof(value_cbor_prefix), &value_cbor_prefix_len)) {
375     return false;
376   }
377 
378   UwCryptoHmacMsg messages[] = {
379       {bstr_cbor_prefix, bstr_cbor_prefix_len},
380       {caveat->bytes, caveat->num_bytes},
381       {value_cbor_prefix, value_cbor_prefix_len},
382       {context->ble_session_id, context->ble_session_id_len},
383   };
384 
385   return uw_crypto_hmac_(key, key_len, messages,
386                          sizeof(messages) / sizeof(messages[0]), mac_tag,
387                          mac_tag_size);
388 }
389 
update_and_check_expiration_time(uint32_t current_time,uint32_t new_expiration_time,UwMacaroonValidationResult * result)390 static bool update_and_check_expiration_time(
391     uint32_t current_time,
392     uint32_t new_expiration_time,
393     UwMacaroonValidationResult* result) {
394   if (result->expiration_time > new_expiration_time) {
395     result->expiration_time = new_expiration_time;
396   }
397 
398   return current_time <= result->expiration_time;
399 }
400 
update_delegatee_list(UwMacaroonCaveatType caveat_type,const UwMacaroonCaveat * caveat,uint32_t issued_time,UwMacaroonValidationResult * result)401 static bool update_delegatee_list(UwMacaroonCaveatType caveat_type,
402                                   const UwMacaroonCaveat* caveat,
403                                   uint32_t issued_time,
404                                   UwMacaroonValidationResult* result) {
405   if (result->num_delegatees >= MAX_NUM_DELEGATEES || issued_time == 0) {
406     return false;
407   }
408 
409   UwMacaroonDelegateeType delegatee_type = kUwMacaroonDelegateeTypeNone;
410   switch (caveat_type) {
411     case kUwMacaroonCaveatTypeDelegateeUser:
412       delegatee_type = kUwMacaroonDelegateeTypeUser;
413       break;
414 
415     case kUwMacaroonCaveatTypeDelegateeApp:
416       delegatee_type = kUwMacaroonDelegateeTypeApp;
417       break;
418 
419     case kUwMacaroonCaveatTypeDelegateeService:
420       delegatee_type = kUwMacaroonDelegateeTypeService;
421       break;
422 
423     default:
424       return false;
425   }
426 
427   if (caveat_type != kUwMacaroonCaveatTypeDelegateeUser) {
428     for (size_t i = 0; i < result->num_delegatees; i++) {
429       // There must have at most one DelegateeApp or DelegateeService
430       if (result->delegatees[i].type == delegatee_type) {
431         return false;
432       }
433     }
434   }
435 
436   if (!uw_macaroon_caveat_get_value_bstr_(
437           caveat, &(result->delegatees[result->num_delegatees].id),
438           &(result->delegatees[result->num_delegatees].id_len))) {
439     return false;
440   }
441   result->delegatees[result->num_delegatees].type = delegatee_type;
442   result->delegatees[result->num_delegatees].timestamp = issued_time;
443   result->num_delegatees++;
444   return true;
445 }
446 
uw_macaroon_caveat_validate_(const UwMacaroonCaveat * caveat,const UwMacaroonContext * context,UwMacaroonValidationState * state,UwMacaroonValidationResult * result)447 bool uw_macaroon_caveat_validate_(const UwMacaroonCaveat* caveat,
448                                   const UwMacaroonContext* context,
449                                   UwMacaroonValidationState* state,
450                                   UwMacaroonValidationResult* result) {
451   if (caveat == NULL || context == NULL || state == NULL || result == NULL) {
452     return false;
453   }
454 
455   uint32_t expiration_time = 0;
456   uint32_t issued_time = 0;
457   uint32_t scope = UW_MACAROON_CAVEAT_SCOPE_LOWEST_POSSIBLE;
458 
459   UwMacaroonCaveatType caveat_type;
460   if (!uw_macaroon_caveat_get_type_(caveat, &caveat_type)) {
461     return false;
462   }
463 
464   switch (caveat_type) {
465     // The types that always validate
466     case kUwMacaroonCaveatTypeClientAuthorizationTokenV1:
467     case kUwMacaroonCaveatTypeServerAuthenticationTokenV1:
468     case kUwMacaroonCaveatTypeNonce:
469     case kUwMacaroonCaveatTypeBleSessionID:
470       return true;
471 
472     case kUwMacaroonCaveatTypeDelegationTimestamp:
473       if (!uw_macaroon_caveat_get_value_uint_(caveat, &issued_time) ||
474           issued_time < state->issued_time) {
475         return false;
476       }
477       state->issued_time = issued_time;
478       return true;
479 
480     case kUwMacaroonCaveatTypeTTL1Hour:
481       if (state->issued_time == 0) {
482         return false;
483       }
484       return update_and_check_expiration_time(
485           context->current_time, state->issued_time + 60 * 60, result);
486 
487     case kUwMacaroonCaveatTypeTTL24Hour:
488       if (state->issued_time == 0) {
489         return false;
490       }
491       return update_and_check_expiration_time(
492           context->current_time, state->issued_time + 24 * 60 * 60, result);
493 
494     // Need to create a list of delegatees
495     case kUwMacaroonCaveatTypeDelegateeUser:
496     case kUwMacaroonCaveatTypeDelegateeApp:
497     case kUwMacaroonCaveatTypeDelegateeService:
498       return update_delegatee_list(caveat_type, caveat, state->issued_time,
499                                    result);
500 
501     // Time related caveats
502     case kUwMacaroonCaveatTypeExpirationAbsolute:
503       if (!uw_macaroon_caveat_get_value_uint_(caveat, &expiration_time)) {
504         return false;
505       }
506       return update_and_check_expiration_time(context->current_time,
507                                               expiration_time, result);
508 
509     // The caveats that update the values of the result object
510     case kUwMacaroonCaveatTypeScope:
511       if (!uw_macaroon_caveat_get_value_uint_(caveat, &scope) ||
512           // Larger value means less priviledge
513           scope > UW_MACAROON_CAVEAT_SCOPE_LOWEST_POSSIBLE) {
514         return false;
515       }
516       if (scope > (uint32_t)(result->granted_scope)) {
517         result->granted_scope = (UwMacaroonCaveatScopeType)scope;
518       }
519       return true;
520 
521     case kUwMacaroonCaveatTypeAppCommandsOnly:
522       result->weave_app_restricted = true;
523       return true;
524 
525     case kUwMacaroonCaveatTypeLanSessionID:
526       return uw_macaroon_caveat_get_value_bstr_(
527           caveat, &(result->lan_session_id), &(result->lan_session_id_len));
528   }
529 
530   return false;
531 }
532 
uw_macaroon_caveat_get_value_uint_(const UwMacaroonCaveat * caveat,uint32_t * unsigned_int)533 bool uw_macaroon_caveat_get_value_uint_(const UwMacaroonCaveat* caveat,
534                                         uint32_t* unsigned_int) {
535   if (caveat == NULL || unsigned_int == NULL) {
536     return false;
537   }
538 
539   UwMacaroonCaveatType type;
540   if (!uw_macaroon_caveat_get_type_(caveat, &type)) {
541     return false;
542   }
543   if (type != kUwMacaroonCaveatTypeScope &&
544       type != kUwMacaroonCaveatTypeExpirationAbsolute &&
545       type != kUwMacaroonCaveatTypeDelegationTimestamp) {
546     // Wrong type
547     return false;
548   }
549 
550   // Skip the portion for CBOR type
551   size_t offset;
552   if (!uw_macaroon_encoding_get_item_len_(caveat->bytes, caveat->num_bytes,
553                                           &offset)) {
554     return false;
555   }
556 
557   return uw_macaroon_encoding_decode_uint_(
558       caveat->bytes + offset, caveat->num_bytes - offset, unsigned_int);
559 }
560 
uw_macaroon_caveat_get_value_bstr_(const UwMacaroonCaveat * caveat,const uint8_t ** str,size_t * str_len)561 bool uw_macaroon_caveat_get_value_bstr_(const UwMacaroonCaveat* caveat,
562                                         const uint8_t** str,
563                                         size_t* str_len) {
564   if (caveat == NULL || str == NULL || str_len == NULL) {
565     return false;
566   }
567 
568   UwMacaroonCaveatType type;
569   if (!uw_macaroon_caveat_get_type_(caveat, &type)) {
570     return false;
571   }
572   if (type != kUwMacaroonCaveatTypeNonce &&
573       type != kUwMacaroonCaveatTypeDelegateeUser &&
574       type != kUwMacaroonCaveatTypeDelegateeApp &&
575       type != kUwMacaroonCaveatTypeDelegateeService &&
576       type != kUwMacaroonCaveatTypeLanSessionID &&
577       type != kUwMacaroonCaveatTypeClientAuthorizationTokenV1 &&
578       type != kUwMacaroonCaveatTypeServerAuthenticationTokenV1) {
579     // Wrong type
580     return false;
581   }
582 
583   size_t offset;
584   if (!uw_macaroon_encoding_get_item_len_(caveat->bytes, caveat->num_bytes,
585                                           &offset)) {
586     return false;
587   }
588 
589   return uw_macaroon_encoding_decode_byte_str_(
590       caveat->bytes + offset, caveat->num_bytes - offset, str, str_len);
591 }
592 
uw_macaroon_caveat_init_validation_state_(UwMacaroonValidationState * state)593 bool uw_macaroon_caveat_init_validation_state_(
594     UwMacaroonValidationState* state) {
595   if (state == NULL) {
596     return false;
597   }
598 
599   state->issued_time = 0;
600   return true;
601 }
602