Update macaroon lib

Change-Id: I71f2aacbc094b3e4cbd10898d037719ac59c4015
Reviewed-on: https://weave-review.googlesource.com/2359
Reviewed-by: Vitaly Buka <vitalybuka@google.com>
diff --git a/third_party/libuweave/src/crypto_hmac.h b/third_party/libuweave/src/crypto_hmac.h
index bac634a..6f76ed0 100644
--- a/third_party/libuweave/src/crypto_hmac.h
+++ b/third_party/libuweave/src/crypto_hmac.h
@@ -9,21 +9,21 @@
 #include <stddef.h>
 #include <stdint.h>
 
-// Return the minimum required number of bytes for the state_buffer used in the
-// init, update and final functions.
-size_t uw_crypto_hmac_required_buffer_size_();
+typedef struct {
+  const uint8_t* bytes;
+  size_t num_bytes;
+} UwCryptoHmacMsg;
 
-bool uw_crypto_hmac_init_(uint8_t* state_buffer,
-                          size_t state_buffer_len,
-                          const uint8_t* key,
-                          size_t key_len);
-bool uw_crypto_hmac_update_(uint8_t* state_buffer,
-                            size_t state_buffer_len,
-                            const uint8_t* data,
-                            size_t data_len);
-bool uw_crypto_hmac_final_(uint8_t* state_buffer,
-                           size_t state_buffer_len,
-                           uint8_t* truncated_digest,
-                           size_t truncated_digest_len);
+/**
+ * Compute HMAC over a list of messages, which is equivalent to computing HMAC
+ * over the concatenation of all the messages. The HMAC output will be truncated
+ * to the desired length truncated_digest_len, and written into trucated_digest.
+ */
+bool uw_crypto_hmac_(const uint8_t* key,
+                     size_t key_len,
+                     const UwCryptoHmacMsg messages[],
+                     size_t num_messages,
+                     uint8_t* truncated_digest,
+                     size_t truncated_digest_len);
 
 #endif  // LIBUWEAVE_SRC_CRYPTO_HMAC_H_
diff --git a/third_party/libuweave/src/crypto_utils.c b/third_party/libuweave/src/crypto_utils.c
index 76b8068..7a6e38f 100644
--- a/third_party/libuweave/src/crypto_utils.c
+++ b/third_party/libuweave/src/crypto_utils.c
@@ -7,13 +7,6 @@
 bool uw_crypto_utils_equal_(const uint8_t* arr1,
                             const uint8_t* arr2,
                             size_t len) {
-  if (arr1 == NULL || arr2 == NULL) {
-    if (arr1 == NULL && arr2 == NULL && len == 0) {
-      return true;
-    }
-    return false;
-  }
-
   uint8_t diff = 0;
   for (size_t i = 0; i < len; i++) {
     diff |= arr1[i] ^ arr2[i];
diff --git a/third_party/libuweave/src/macaroon.c b/third_party/libuweave/src/macaroon.c
index 70afda1..50b2d00 100644
--- a/third_party/libuweave/src/macaroon.c
+++ b/third_party/libuweave/src/macaroon.c
@@ -8,13 +8,17 @@
 
 #include "src/crypto_utils.h"
 #include "src/macaroon_caveat.h"
+#include "src/macaroon_caveat_internal.h"
 #include "src/macaroon_encoding.h"
 
-static bool create_mac_tag_(const uint8_t* key, size_t key_len,
-                            const UwMacaroonCaveat* caveats, size_t num_caveats,
+static bool create_mac_tag_(const uint8_t* key,
+                            size_t key_len,
+                            const UwMacaroonContext* context,
+                            const UwMacaroonCaveat* const caveats[],
+                            size_t num_caveats,
                             uint8_t mac_tag[UW_MACAROON_MAC_LEN]) {
-  if (key == NULL || key_len == 0 || caveats == NULL || num_caveats == 0 ||
-      mac_tag == NULL) {
+  if (key == NULL || key_len == 0 || context == NULL || caveats == NULL ||
+      num_caveats == 0 || mac_tag == NULL) {
     return false;
   }
 
@@ -26,15 +30,15 @@
   uint8_t mac_tag_buff[UW_MACAROON_MAC_LEN];
 
   // Compute the first tag by using the key
-  if (!uw_macaroon_caveat_sign_(key, key_len, &(caveats[0]), mac_tag_buff,
+  if (!uw_macaroon_caveat_sign_(key, key_len, context, caveats[0], mac_tag_buff,
                                 UW_MACAROON_MAC_LEN)) {
     return false;
   }
 
   // Compute the rest of the tags by using the tag as the key
   for (size_t i = 1; i < num_caveats; i++) {
-    if (!uw_macaroon_caveat_sign_(mac_tag_buff, UW_MACAROON_MAC_LEN,
-                                  &(caveats[i]), mac_tag_buff,
+    if (!uw_macaroon_caveat_sign_(mac_tag_buff, UW_MACAROON_MAC_LEN, context,
+                                  caveats[i], mac_tag_buff,
                                   UW_MACAROON_MAC_LEN)) {
       return false;
     }
@@ -44,33 +48,38 @@
   return true;
 }
 
-bool uw_macaroon_new_from_mac_tag_(UwMacaroon* new_macaroon,
-                                   const uint8_t mac_tag[UW_MACAROON_MAC_LEN],
-                                   const UwMacaroonCaveat* caveats,
-                                   size_t num_caveats) {
-  if (new_macaroon == NULL || mac_tag == NULL || caveats == NULL ||
-      num_caveats == 0) {
+static bool verify_mac_tag_(const uint8_t* root_key,
+                            size_t root_key_len,
+                            const UwMacaroonContext* context,
+                            const UwMacaroonCaveat* const caveats[],
+                            size_t num_caveats,
+                            const uint8_t mac_tag[UW_MACAROON_MAC_LEN]) {
+  if (root_key == NULL || root_key_len == 0 || context == NULL ||
+      caveats == NULL || num_caveats == 0 || mac_tag == 0) {
     return false;
   }
 
-  memcpy(new_macaroon->mac_tag, mac_tag, UW_MACAROON_MAC_LEN);
-  new_macaroon->num_caveats = num_caveats;
-  new_macaroon->caveats = caveats;
+  uint8_t computed_mac_tag[UW_MACAROON_MAC_LEN] = {0};
+  if (!create_mac_tag_(root_key, root_key_len, context, caveats, num_caveats,
+                       computed_mac_tag)) {
+    return false;
+  }
 
-  return true;
+  return uw_crypto_utils_equal_(mac_tag, computed_mac_tag, UW_MACAROON_MAC_LEN);
 }
 
-bool uw_macaroon_new_from_root_key_(UwMacaroon* new_macaroon,
-                                    const uint8_t* root_key,
-                                    size_t root_key_len,
-                                    const UwMacaroonCaveat* caveats,
-                                    size_t num_caveats) {
-  if (new_macaroon == NULL || root_key == NULL || root_key_len == 0 ||
-      caveats == NULL || num_caveats == 0) {
+bool uw_macaroon_create_from_root_key_(UwMacaroon* new_macaroon,
+                                       const uint8_t* root_key,
+                                       size_t root_key_len,
+                                       const UwMacaroonContext* context,
+                                       const UwMacaroonCaveat* const caveats[],
+                                       size_t num_caveats) {
+  if (new_macaroon == NULL || root_key == NULL || context == NULL ||
+      root_key_len == 0 || caveats == NULL || num_caveats == 0) {
     return false;
   }
 
-  if (!create_mac_tag_(root_key, root_key_len, caveats, num_caveats,
+  if (!create_mac_tag_(root_key, root_key_len, context, caveats, num_caveats,
                        new_macaroon->mac_tag)) {
     return false;
   }
@@ -81,139 +90,228 @@
   return true;
 }
 
-bool uw_macaroon_verify_(const UwMacaroon* macaroon,
-                         const uint8_t* root_key,
-                         size_t root_key_len) {
-  if (macaroon == NULL || root_key == NULL) {
-    return false;
-  }
-
-  uint8_t mac_tag[UW_MACAROON_MAC_LEN] = {0};
-  if (!create_mac_tag_(root_key, root_key_len, macaroon->caveats,
-                       macaroon->num_caveats, mac_tag)) {
-    return false;
-  }
-
-  return uw_crypto_utils_equal_(mac_tag, macaroon->mac_tag,
-                                UW_MACAROON_MAC_LEN);
-}
-
 bool uw_macaroon_extend_(const UwMacaroon* old_macaroon,
                          UwMacaroon* new_macaroon,
+                         const UwMacaroonContext* context,
                          const UwMacaroonCaveat* additional_caveat,
-                         uint8_t* buffer, size_t buffer_size) {
-  if (old_macaroon == NULL || new_macaroon == NULL ||
+                         uint8_t* buffer,
+                         size_t buffer_size) {
+  if (old_macaroon == NULL || new_macaroon == NULL || context == NULL ||
       additional_caveat == NULL || buffer == NULL || buffer_size == 0) {
     return false;
   }
 
   new_macaroon->num_caveats = old_macaroon->num_caveats + 1;
 
-  // Extend the caveat list
-  if ((new_macaroon->num_caveats) * sizeof(UwMacaroonCaveat) > buffer_size) {
-    // Not enough memory to store the extended caveat list
+  // Extend the caveat pointer list
+  if ((new_macaroon->num_caveats) * sizeof(UwMacaroonCaveat*) > buffer_size) {
+    // Not enough memory to store the extended caveat pointer list
     return false;
   }
-  UwMacaroonCaveat* extended_list = (UwMacaroonCaveat*)buffer;
-  if (old_macaroon->caveats != NULL && extended_list != old_macaroon->caveats) {
+  const UwMacaroonCaveat** extended_list = (const UwMacaroonCaveat**)buffer;
+  if (new_macaroon->caveats != old_macaroon->caveats) {
     memcpy(extended_list, old_macaroon->caveats,
-           (old_macaroon->num_caveats) * sizeof(UwMacaroonCaveat));
+           old_macaroon->num_caveats * sizeof(old_macaroon->caveats[0]));
   }
-  extended_list[old_macaroon->num_caveats] = *additional_caveat;
-  new_macaroon->caveats = extended_list;
+  extended_list[old_macaroon->num_caveats] = additional_caveat;
+  new_macaroon->caveats = (const UwMacaroonCaveat* const*)extended_list;
 
   // Compute the new MAC tag
-  return create_mac_tag_(old_macaroon->mac_tag, UW_MACAROON_MAC_LEN,
-                         additional_caveat, 1, new_macaroon->mac_tag);
+  return create_mac_tag_(old_macaroon->mac_tag, UW_MACAROON_MAC_LEN, context,
+                         new_macaroon->caveats + old_macaroon->num_caveats, 1,
+                         new_macaroon->mac_tag);
+}
+
+static void init_validation_result(UwMacaroonValidationResult* result) {
+  // Start from the largest scope
+  result->granted_scope = kUwMacaroonCaveatScopeTypeOwner;
+  result->expiration_time = UINT32_MAX;
+  result->weave_app_restricted = false;
+  result->lan_session_id = NULL;
+  result->lan_session_id_len = 0;
+  result->num_delegatees = 0;
+}
+
+/** Reset the result object to the lowest scope when encountering errors */
+static void reset_validation_result(UwMacaroonValidationResult* result) {
+  // Start from the largest scope or highest privilege
+  result->granted_scope =
+      (UwMacaroonCaveatScopeType)UW_MACAROON_CAVEAT_SCOPE_LOWEST_POSSIBLE;
+  result->expiration_time = 0;
+  result->weave_app_restricted = true;
+  result->lan_session_id = NULL;
+  result->lan_session_id_len = 0;
+
+  result->num_delegatees = 0;
+  for (size_t i = 0; i < MAX_NUM_DELEGATEES; i++) {
+    result->delegatees[i].id = NULL;
+    result->delegatees[i].id_len = 0;
+    result->delegatees[i].is_app = true;
+  }
+}
+
+bool uw_macaroon_validate_(const UwMacaroon* macaroon,
+                           const uint8_t* root_key,
+                           size_t root_key_len,
+                           const UwMacaroonContext* context,
+                           UwMacaroonValidationResult* result) {
+  if (result == NULL) {
+    return false;
+  }
+  init_validation_result(result);
+
+  if (root_key == NULL || root_key_len == 0 || macaroon == NULL ||
+      context == NULL || result == NULL ||
+      !verify_mac_tag_(root_key, root_key_len, context, macaroon->caveats,
+                       macaroon->num_caveats, macaroon->mac_tag)) {
+    return false;
+  }
+
+  UwMacaroonValidationState state;
+  if (!uw_macaroon_caveat_init_validation_state_(&state)) {
+    return false;
+  }
+  for (size_t i = 0; i < macaroon->num_caveats; i++) {
+    if (!uw_macaroon_caveat_validate_(macaroon->caveats[i], context, &state,
+                                      result)) {
+      reset_validation_result(result);  // Reset the result object
+      return false;
+    }
+  }
+
+  return true;
 }
 
 // Encode a Macaroon to a byte string
-bool uw_macaroon_dump_(const UwMacaroon* macaroon,
-                       uint8_t* out,
-                       size_t out_len,
-                       size_t* resulting_str_len) {
-  if (macaroon == NULL || out == NULL || out_len == 0 ||
+bool uw_macaroon_serialize_(const UwMacaroon* macaroon,
+                            uint8_t* out,
+                            size_t out_len,
+                            size_t* resulting_str_len) {
+  if (macaroon == NULL || out == NULL ||
+      out_len < UW_MACAROON_ENCODING_MAX_UINT_CBOR_LEN ||
       resulting_str_len == NULL) {
     return false;
   }
 
-  size_t offset = 0, item_len;
+  // Need to encode the whole Macaroon again into a byte string.
 
-  if (!uw_macaroon_encoding_encode_byte_str_(
-          macaroon->mac_tag, UW_MACAROON_MAC_LEN, out, out_len, &item_len)) {
-    return false;
-  }
-  offset += item_len;
-
-  if (!uw_macaroon_encoding_encode_array_len_(
-          (uint32_t)(macaroon->num_caveats), out + offset, out_len - offset, &item_len)) {
+  // First encode the part without the overall byte string header to the buffer
+  // to get the total length.
+  size_t item_len = 0;
+  // Start with an offset
+  size_t offset = UW_MACAROON_ENCODING_MAX_UINT_CBOR_LEN;
+  if (!uw_macaroon_encoding_encode_array_len_((uint32_t)(macaroon->num_caveats),
+                                              out + offset, out_len - offset,
+                                              &item_len)) {
     return false;
   }
   offset += item_len;
 
   for (size_t i = 0; i < macaroon->num_caveats; i++) {
     if (!uw_macaroon_encoding_encode_byte_str_(
-            macaroon->caveats[i].bytes, macaroon->caveats[i].num_bytes,
+            macaroon->caveats[i]->bytes, macaroon->caveats[i]->num_bytes,
             out + offset, out_len - offset, &item_len)) {
       return false;
     }
     offset += item_len;
   }
 
-  *resulting_str_len = offset;
+  if (!uw_macaroon_encoding_encode_byte_str_(macaroon->mac_tag,
+                                             UW_MACAROON_MAC_LEN, out + offset,
+                                             out_len - offset, &item_len)) {
+    return false;
+  }
+  offset += item_len;
+
+  // Encode the length of the body at the beginning of the buffer
+  size_t bstr_len = offset - UW_MACAROON_ENCODING_MAX_UINT_CBOR_LEN;
+  if (!uw_macaroon_encoding_encode_byte_str_len_(
+          bstr_len, out, UW_MACAROON_ENCODING_MAX_UINT_CBOR_LEN, &item_len)) {
+    return false;
+  }
+
+  // Move the body part to be adjacent to the byte string header part
+  memmove(out + item_len, out + UW_MACAROON_ENCODING_MAX_UINT_CBOR_LEN,
+          bstr_len);
+
+  *resulting_str_len = item_len + bstr_len;
   return true;
 }
 
 // Decode a byte string to a Macaroon
-bool uw_macaroon_load_(const uint8_t* in,
-                       size_t in_len,
-                       uint8_t* caveats_buffer,
-                       size_t caveats_buffer_size,
-                       UwMacaroon* macaroon) {
-  if (in == NULL || in_len == 0 || caveats_buffer == NULL ||
-      caveats_buffer_size == 0 || macaroon == NULL) {
+bool uw_macaroon_deserialize_(const uint8_t* in,
+                              size_t in_len,
+                              uint8_t* buffer,
+                              size_t buffer_size,
+                              UwMacaroon* macaroon) {
+  if (in == NULL || in_len == 0 || buffer == NULL || buffer_size == 0 ||
+      macaroon == NULL) {
     return false;
   }
 
-  const uint8_t* tag;
-  size_t tag_len;
-  if (!uw_macaroon_encoding_decode_byte_str_(in, in_len, &tag, &tag_len) ||
-      tag_len != UW_MACAROON_MAC_LEN) {
+  size_t offset = 0;
+  size_t item_len = 0;
+
+  const uint8_t* bstr = NULL;
+  size_t bstr_len = 0;
+  if (!uw_macaroon_encoding_decode_byte_str_(in + offset, in_len - offset,
+                                             &bstr, &bstr_len)) {
     return false;
   }
-  memcpy(macaroon->mac_tag, tag, UW_MACAROON_MAC_LEN);
+  item_len = bstr - in;  // The length of the first byte string header
+  offset += item_len;
 
-  size_t offset = 0, cbor_item_len;
-  if (!uw_macaroon_encoding_get_item_len_(in, in_len, &cbor_item_len)) {
+  if (item_len + bstr_len != in_len) {
+    // The string length doesn't match
     return false;
   }
-  offset += cbor_item_len;
 
-  uint32_t array_len;
+  uint32_t array_len = 0;
   if (!uw_macaroon_encoding_decode_array_len_(in + offset, in_len - offset,
                                               &array_len)) {
     return false;
   }
   macaroon->num_caveats = (size_t)array_len;
-  if (caveats_buffer_size < array_len * sizeof(UwMacaroonCaveat)) {
+  if (buffer_size <
+      (array_len * (sizeof(UwMacaroonCaveat) + sizeof(UwMacaroonCaveat*)))) {
+    // Need two levels of abstraction, one for structs and one for pointers
     return false;
   }
 
-  UwMacaroonCaveat* caveats = (UwMacaroonCaveat*)caveats_buffer;
-  for (size_t i = 0; i < array_len; i++) {
-    if (!uw_macaroon_encoding_get_item_len_(in + offset, in_len - offset,
-                                            &cbor_item_len)) {
-      return false;
-    }
-    offset += cbor_item_len;
-
-    if (!uw_macaroon_encoding_decode_byte_str_(in + offset, in_len - offset,
-                                               &(caveats[i].bytes),
-                                               &(caveats[i].num_bytes))) {
-      return false;
-    }
+  if (!uw_macaroon_encoding_get_item_len_(in + offset, in_len - offset,
+                                          &item_len)) {
+    return false;
   }
-  macaroon->caveats = caveats;
+  offset += item_len;
+
+  const UwMacaroonCaveat** caveat_pointers = (const UwMacaroonCaveat**)buffer;
+  buffer += array_len * sizeof(UwMacaroonCaveat*);
+  UwMacaroonCaveat* caveat_structs = (UwMacaroonCaveat*)buffer;
+  for (size_t i = 0; i < array_len; i++) {
+    caveat_pointers[i] = &(caveat_structs[i]);
+
+    if (!uw_macaroon_encoding_decode_byte_str_(
+            in + offset, in_len - offset, &(caveat_structs[i].bytes),
+            &(caveat_structs[i].num_bytes))) {
+      return false;
+    }
+
+    if (!uw_macaroon_encoding_get_item_len_(in + offset, in_len - offset,
+                                            &item_len)) {
+      return false;
+    }
+    offset += item_len;
+  }
+  macaroon->caveats = caveat_pointers;
+
+  const uint8_t* tag;
+  size_t tag_len;
+  if (!uw_macaroon_encoding_decode_byte_str_(in + offset, in_len - offset, &tag,
+                                             &tag_len) ||
+      tag_len != UW_MACAROON_MAC_LEN) {
+    return false;
+  }
+  memcpy(macaroon->mac_tag, tag, UW_MACAROON_MAC_LEN);
 
   return true;
 }
diff --git a/third_party/libuweave/src/macaroon.h b/third_party/libuweave/src/macaroon.h
index 61242f7..dfaaba7 100644
--- a/third_party/libuweave/src/macaroon.h
+++ b/third_party/libuweave/src/macaroon.h
@@ -9,7 +9,8 @@
 #include <stddef.h>
 #include <stdint.h>
 
-#include "macaroon_caveat.h"
+#include "src/macaroon_caveat.h"
+#include "src/macaroon_context.h"
 
 #define UW_MACAROON_MAC_LEN 16
 
@@ -20,45 +21,71 @@
 typedef struct {
   uint8_t mac_tag[UW_MACAROON_MAC_LEN];
   size_t num_caveats;
-  const UwMacaroonCaveat* caveats;
+  const UwMacaroonCaveat* const* caveats;
 } UwMacaroon;
 
-bool uw_macaroon_new_from_mac_tag_(UwMacaroon* new_macaroon,
-                                   const uint8_t mac_tag[UW_MACAROON_MAC_LEN],
-                                   const UwMacaroonCaveat* caveats,
-                                   size_t num_caveats);
+// For the delegatee list in the validation result object
+typedef struct {
+  const uint8_t* id;
+  size_t id_len;
+  bool is_app;
+} UwMacaroonDelegateeInfo;
 
-bool uw_macaroon_new_from_root_key_(UwMacaroon* new_macaroon,
-                                    const uint8_t* root_key,
-                                    size_t root_key_len,
-                                    const UwMacaroonCaveat* caveats,
-                                    size_t num_caveats);
+#define MAX_NUM_DELEGATEES 10
 
-bool uw_macaroon_verify_(const UwMacaroon* macaroon,
-                         const uint8_t* root_key,
-                         size_t root_key_len);
+typedef struct {
+  UwMacaroonCaveatScopeType granted_scope;
+  uint32_t expiration_time;
+  bool weave_app_restricted;
+  const uint8_t* lan_session_id;
+  size_t lan_session_id_len;
+  UwMacaroonDelegateeInfo delegatees[MAX_NUM_DELEGATEES];
+  size_t num_delegatees;
+} UwMacaroonValidationResult;
 
-// Create a new macaroon with a new caveat
+bool uw_macaroon_create_from_root_key_(UwMacaroon* new_macaroon,
+                                       const uint8_t* root_key,
+                                       size_t root_key_len,
+                                       const UwMacaroonContext* context,
+                                       const UwMacaroonCaveat* const caveats[],
+                                       size_t num_caveats);
+
+/** Creates a new macaroon with a new caveat. */
 bool uw_macaroon_extend_(const UwMacaroon* old_macaroon,
                          UwMacaroon* new_macaroon,
+                         const UwMacaroonContext* context,
                          const UwMacaroonCaveat* additional_caveat,
-                         uint8_t* buffer, size_t buffer_size);
+                         uint8_t* buffer,
+                         size_t buffer_size);
 
-// Encode a Macaroon to a byte string
-bool uw_macaroon_dump_(const UwMacaroon* macaroon,
-                       uint8_t* out,
-                       size_t out_len,
-                       size_t* resulting_str_len);
+/**
+ * Verify and validate the Macaroon, and put relevant information into the
+ * result object.
+ */
+bool uw_macaroon_validate_(
+    const UwMacaroon* macaroon,
+    const uint8_t* root_key,
+    size_t root_key_len,
+    const UwMacaroonContext* context,
+    UwMacaroonValidationResult* result);
 
-// Decode a byte string to a Macaroon (the caveats_buffer here is used only for
-// the caveat pointer list *caveats in the UwMacaroon *macaroon). One note is
-// that the function doesn't copy string values to new buffers, so the caller
-// may maintain the input string around to make caveats with string values to
-// be usuable.
-bool uw_macaroon_load_(const uint8_t* in,
-                       size_t in_len,
-                       uint8_t* caveats_buffer,
-                       size_t caveats_buffer_size,
-                       UwMacaroon* macaroon);
+/** Encode a Macaroon to a byte string. */
+bool uw_macaroon_serialize_(const UwMacaroon* macaroon,
+                            uint8_t* out,
+                            size_t out_len,
+                            size_t* resulting_str_len);
+
+/**
+ * Decodes a byte string to a Macaroon.
+ *
+ * One note is that the function doesn't copy string values to new buffers, so
+ * the caller must maintain the input string around to make caveats with string
+ * values to be usable.
+ */
+bool uw_macaroon_deserialize_(const uint8_t* in,
+                              size_t in_len,
+                              uint8_t* buffer,
+                              size_t buffer_size,
+                              UwMacaroon* new_macaroon);
 
 #endif  // LIBUWEAVE_SRC_MACAROON_H_
diff --git a/third_party/libuweave/src/macaroon_caveat.c b/third_party/libuweave/src/macaroon_caveat.c
index 594f9de..b8b2183 100644
--- a/third_party/libuweave/src/macaroon_caveat.c
+++ b/third_party/libuweave/src/macaroon_caveat.c
@@ -3,125 +3,287 @@
 // found in the LICENSE file.
 
 #include "src/macaroon_caveat.h"
+#include "src/macaroon_caveat_internal.h"
 
 #include <string.h>
 
 #include "src/crypto_hmac.h"
+#include "src/macaroon.h"
 #include "src/macaroon_context.h"
 #include "src/macaroon_encoding.h"
 
-// TODO(bozhu): Find a better way to pre-allocate memory for HMACc computations?
-// Are C99 variable-length arrays allowed on embedded devices?
-#define HMAC_STATE_BUFFER_SIZE 1024
+#define MAX_CBOR_STR_LEN_FOR_UINT 5
 
-static bool create_caveat_(UwMacaroonCaveatType type, const void* value,
-                           size_t value_len, uint8_t* buffer,
-                           size_t buffer_size, UwMacaroonCaveat* caveat) {
-  if (buffer == NULL || buffer_size == 0 || caveat == NULL) {
-    // Here value can be NULL, and value_len can be 0
+static bool is_valid_caveat_type_(UwMacaroonCaveatType type) {
+  switch (type) {
+    case kUwMacaroonCaveatTypeNonce:
+    case kUwMacaroonCaveatTypeScope:
+    case kUwMacaroonCaveatTypeExpirationAbsolute:
+    case kUwMacaroonCaveatTypeTTL1Hour:
+    case kUwMacaroonCaveatTypeTTL24Hour:
+    case kUwMacaroonCaveatTypeDelegationTimestamp:
+    case kUwMacaroonCaveatTypeDelegateeUser:
+    case kUwMacaroonCaveatTypeDelegateeApp:
+    case kUwMacaroonCaveatTypeAppCommandsOnly:
+    case kUwMacaroonCaveatTypeBleSessionID:
+    case kUwMacaroonCaveatTypeLanSessionID:
+    case kUwMacaroonCaveatTypeClientAuthorizationTokenV1:
+    case kUwMacaroonCaveatTypeServerAuthenticationTokenV1:
+      return true;
+  }
+  return false;
+}
+
+static bool is_valid_scope_type_(UwMacaroonCaveatScopeType type) {
+  switch (type) {
+    case kUwMacaroonCaveatScopeTypeOwner:
+    case kUwMacaroonCaveatScopeTypeManager:
+    case kUwMacaroonCaveatScopeTypeUser:
+    case kUwMacaroonCaveatScopeTypeViewer:
+      return true;
+  }
+  return false;
+}
+
+static bool create_caveat_no_value_(UwMacaroonCaveatType type,
+                                    uint8_t* buffer,
+                                    size_t buffer_size,
+                                    UwMacaroonCaveat* new_caveat) {
+  // (buffer_size == 0 || get_buffer_size_() > buffer_size) will conver the case
+  // that get_buffer_size_() returns 0 (for errors), so there is no need to
+  // check get_buffer_size_() == 0 again.
+  if (buffer == NULL || buffer_size == 0 || new_caveat == NULL ||
+      uw_macaroon_caveat_creation_get_buffsize_(type, 0) > buffer_size) {
     return false;
   }
 
-  caveat->bytes = buffer;
-  size_t encoded_str_len, total_str_len;
-
-  uint32_t unsigned_int = (uint32_t)type;
-  if (!uw_macaroon_encoding_encode_uint_(unsigned_int, buffer, buffer_size,
+  size_t encoded_str_len = 0, total_str_len = 0;
+  if (!uw_macaroon_encoding_encode_uint_((uint32_t)type, buffer, buffer_size,
                                          &encoded_str_len)) {
     return false;
   }
-  total_str_len = encoded_str_len;
-  buffer += encoded_str_len;
-  buffer_size -= encoded_str_len;
-
-  switch (type) {
-    case kUwMacaroonCaveatTypeStop:
-    case kUwMacaroonCaveatTypeSessionIdentifier:
-      // No value
-      encoded_str_len = 0;
-      break;
-
-    case kUwMacaroonCaveatTypeScope:
-    case kUwMacaroonCaveatTypeIssued:
-    case kUwMacaroonCaveatTypeTTL:
-    case kUwMacaroonCaveatTypeExpiration:
-      // Integer
-      if (value_len != sizeof(uint32_t)) {
-        // Wrong size for integers
-        return false;
-      }
-      unsigned_int = *((uint32_t*)value);
-      if (!uw_macaroon_encoding_encode_uint_(unsigned_int, buffer, buffer_size,
-                                             &encoded_str_len)) {
-        return false;
-      }
-      break;
-
-    case kUwMacaroonCaveatTypeIdentifier:
-      // Text string
-      if (!uw_macaroon_encoding_encode_text_str_((uint8_t*)value, value_len,
-                                                 buffer, buffer_size,
-                                                 &encoded_str_len)) {
-        return false;
-      }
-      break;
-
-    default:
-      // Should never reach here
-      return false;
-  }
-
   total_str_len += encoded_str_len;
-  caveat->num_bytes = total_str_len;
+
+  new_caveat->bytes = buffer;
+  new_caveat->num_bytes = total_str_len;
   return true;
 }
 
-bool uw_macaroon_caveat_create_without_value_(UwMacaroonCaveatType type,
+static bool create_caveat_uint_value_(UwMacaroonCaveatType type,
+                                      uint32_t unsigned_int,
+                                      uint8_t* buffer,
+                                      size_t buffer_size,
+                                      UwMacaroonCaveat* new_caveat) {
+  if (buffer == NULL || buffer_size == 0 || new_caveat == NULL ||
+      uw_macaroon_caveat_creation_get_buffsize_(type, 0) > buffer_size) {
+    return false;
+  }
+
+  size_t encoded_str_len = 0, total_str_len = 0;
+  if (!uw_macaroon_encoding_encode_uint_((uint32_t)type, buffer, buffer_size,
+                                         &encoded_str_len)) {
+    return false;
+  }
+  total_str_len += encoded_str_len;
+  if (!uw_macaroon_encoding_encode_uint_(unsigned_int, buffer + total_str_len,
+                                         buffer_size - total_str_len,
+                                         &encoded_str_len)) {
+    return false;
+  }
+  total_str_len += encoded_str_len;
+
+  new_caveat->bytes = buffer;
+  new_caveat->num_bytes = total_str_len;
+  return true;
+}
+
+static bool create_caveat_bstr_value_(UwMacaroonCaveatType type,
+                                      const uint8_t* str,
+                                      size_t str_len,
+                                      uint8_t* buffer,
+                                      size_t buffer_size,
+                                      UwMacaroonCaveat* new_caveat) {
+  if ((str == NULL && str_len != 0) || buffer == NULL || buffer_size == 0 ||
+      new_caveat == NULL ||
+      uw_macaroon_caveat_creation_get_buffsize_(type, str_len) > buffer_size) {
+    return false;
+  }
+
+  size_t encoded_str_len = 0, total_str_len = 0;
+  if (!uw_macaroon_encoding_encode_uint_((uint32_t)type, buffer, buffer_size,
+                                         &encoded_str_len)) {
+    return false;
+  }
+  total_str_len += encoded_str_len;
+  if (!uw_macaroon_encoding_encode_byte_str_(
+          str, str_len, buffer + total_str_len, buffer_size - total_str_len,
+          &encoded_str_len)) {
+    return false;
+  }
+  total_str_len += encoded_str_len;
+
+  new_caveat->bytes = buffer;
+  new_caveat->num_bytes = total_str_len;
+  return true;
+}
+
+size_t uw_macaroon_caveat_creation_get_buffsize_(UwMacaroonCaveatType type,
+                                                 size_t str_len) {
+  switch (type) {
+    // No values
+    case kUwMacaroonCaveatTypeTTL1Hour:
+    case kUwMacaroonCaveatTypeTTL24Hour:
+    case kUwMacaroonCaveatTypeAppCommandsOnly:
+    case kUwMacaroonCaveatTypeBleSessionID:
+      return UW_MACAROON_ENCODING_MAX_UINT_CBOR_LEN;
+
+    // Unsigned integers
+    case kUwMacaroonCaveatTypeScope:
+    case kUwMacaroonCaveatTypeExpirationAbsolute:
+    case kUwMacaroonCaveatTypeDelegationTimestamp:
+      return 2 * UW_MACAROON_ENCODING_MAX_UINT_CBOR_LEN;
+
+    // Byte strings
+    case kUwMacaroonCaveatTypeNonce:
+    case kUwMacaroonCaveatTypeDelegateeUser:
+    case kUwMacaroonCaveatTypeDelegateeApp:
+    case kUwMacaroonCaveatTypeLanSessionID:
+    case kUwMacaroonCaveatTypeClientAuthorizationTokenV1:
+    case kUwMacaroonCaveatTypeServerAuthenticationTokenV1:
+      return str_len + UW_MACAROON_ENCODING_MAX_UINT_CBOR_LEN;
+
+    default:
+      return 0;  // For errors
+  }
+}
+
+bool uw_macaroon_caveat_create_nonce_(const uint8_t* nonce,
+                                      size_t nonce_size,
+                                      uint8_t* buffer,
+                                      size_t buffer_size,
+                                      UwMacaroonCaveat* new_caveat) {
+  return create_caveat_bstr_value_(kUwMacaroonCaveatTypeNonce, nonce,
+                                   nonce_size, buffer, buffer_size, new_caveat);
+}
+
+bool uw_macaroon_caveat_create_scope_(UwMacaroonCaveatScopeType scope,
+                                      uint8_t* buffer,
+                                      size_t buffer_size,
+                                      UwMacaroonCaveat* new_caveat) {
+  if (!is_valid_scope_type_(scope)) {
+    return false;
+  }
+
+  return create_caveat_uint_value_(kUwMacaroonCaveatTypeScope, scope, buffer,
+                                   buffer_size, new_caveat);
+}
+
+bool uw_macaroon_caveat_create_expiration_absolute_(
+    uint32_t expiration_time,
+    uint8_t* buffer,
+    size_t buffer_size,
+    UwMacaroonCaveat* new_caveat) {
+  return create_caveat_uint_value_(kUwMacaroonCaveatTypeExpirationAbsolute,
+                                   expiration_time, buffer, buffer_size,
+                                   new_caveat);
+}
+
+bool uw_macaroon_caveat_create_ttl_1_hour_(uint8_t* buffer,
+                                           size_t buffer_size,
+                                           UwMacaroonCaveat* new_caveat) {
+  return create_caveat_no_value_(kUwMacaroonCaveatTypeTTL1Hour, buffer,
+                                 buffer_size, new_caveat);
+}
+
+bool uw_macaroon_caveat_create_ttl_24_hour_(uint8_t* buffer,
+                                            size_t buffer_size,
+                                            UwMacaroonCaveat* new_caveat) {
+  return create_caveat_no_value_(kUwMacaroonCaveatTypeTTL24Hour, buffer,
+                                 buffer_size, new_caveat);
+}
+
+bool uw_macaroon_caveat_create_delegation_timestamp_(
+    uint32_t timestamp,
+    uint8_t* buffer,
+    size_t buffer_size,
+    UwMacaroonCaveat* new_caveat) {
+  return create_caveat_uint_value_(kUwMacaroonCaveatTypeDelegationTimestamp,
+                                   timestamp, buffer, buffer_size, new_caveat);
+}
+
+bool 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) {
+  return create_caveat_bstr_value_(kUwMacaroonCaveatTypeDelegateeUser, id_str,
+                                   id_str_len, buffer, buffer_size, new_caveat);
+}
+
+bool uw_macaroon_caveat_create_delegatee_app_(const uint8_t* id_str,
+                                              size_t id_str_len,
                                               uint8_t* buffer,
                                               size_t buffer_size,
-                                              UwMacaroonCaveat* caveat) {
-  if (buffer == NULL || buffer_size == 0 || caveat == NULL) {
-    return false;
-  }
-  if (type != kUwMacaroonCaveatTypeStop &&
-      type != kUwMacaroonCaveatTypeSessionIdentifier) {
-    return false;
-  }
-
-  return create_caveat_(type, NULL, 0, buffer, buffer_size, caveat);
+                                              UwMacaroonCaveat* new_caveat) {
+  return create_caveat_bstr_value_(kUwMacaroonCaveatTypeDelegateeApp, id_str,
+                                   id_str_len, buffer, buffer_size, new_caveat);
 }
 
-bool uw_macaroon_caveat_create_with_uint_(UwMacaroonCaveatType type,
-                                          uint32_t value, uint8_t* buffer,
-                                          size_t buffer_size,
-                                          UwMacaroonCaveat* caveat) {
-  if (buffer == NULL || buffer_size == 0 || caveat == NULL) {
-    return false;
-  }
-  if (type != kUwMacaroonCaveatTypeScope &&
-      type != kUwMacaroonCaveatTypeIssued &&
-      type != kUwMacaroonCaveatTypeTTL &&
-      type != kUwMacaroonCaveatTypeExpiration) {
-    return false;
-  }
-
-  return create_caveat_(type, &value, sizeof(uint32_t), buffer, buffer_size,
-                        caveat);
+bool uw_macaroon_caveat_create_app_commands_only_(
+    uint8_t* buffer,
+    size_t buffer_size,
+    UwMacaroonCaveat* new_caveat) {
+  return create_caveat_no_value_(kUwMacaroonCaveatTypeAppCommandsOnly, buffer,
+                                 buffer_size, new_caveat);
 }
 
-bool uw_macaroon_caveat_create_with_str_(UwMacaroonCaveatType type,
-                                         const uint8_t* str, size_t str_len,
-                                         uint8_t* buffer, size_t buffer_size,
-                                         UwMacaroonCaveat* caveat) {
-  if (buffer == NULL || buffer_size == 0 || caveat == NULL ||
-      (str == NULL && str_len != 0)) {
-    return false;
-  }
-  if (type != kUwMacaroonCaveatTypeIdentifier) {
-    return false;
-  }
+bool uw_macaroon_caveat_create_ble_session_id_(uint8_t* buffer,
+                                               size_t buffer_size,
+                                               UwMacaroonCaveat* new_caveat) {
+  return create_caveat_no_value_(kUwMacaroonCaveatTypeBleSessionID, buffer,
+                                 buffer_size, new_caveat);
+}
 
-  return create_caveat_(type, str, str_len, buffer, buffer_size, caveat);
+bool 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) {
+  return create_caveat_bstr_value_(kUwMacaroonCaveatTypeLanSessionID,
+                                   session_id, session_id_len, buffer,
+                                   buffer_size, new_caveat);
+}
+
+bool 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) {
+  if (str_len == 0) {
+    return create_caveat_no_value_(
+        kUwMacaroonCaveatTypeClientAuthorizationTokenV1, buffer, buffer_size,
+        new_caveat);
+  }
+  return create_caveat_bstr_value_(
+      kUwMacaroonCaveatTypeClientAuthorizationTokenV1, str, str_len, buffer,
+      buffer_size, new_caveat);
+}
+
+bool 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) {
+  if (str_len == 0) {
+    return create_caveat_no_value_(
+        kUwMacaroonCaveatTypeServerAuthenticationTokenV1, buffer, buffer_size,
+        new_caveat);
+  }
+  return create_caveat_bstr_value_(
+      kUwMacaroonCaveatTypeServerAuthenticationTokenV1, str, str_len, buffer,
+      buffer_size, new_caveat);
 }
 
 bool uw_macaroon_caveat_get_type_(const UwMacaroonCaveat* caveat,
@@ -137,20 +299,208 @@
   }
 
   *type = (UwMacaroonCaveatType)unsigned_int;
+  return is_valid_caveat_type_(*type);
+}
 
-  if (*type != kUwMacaroonCaveatTypeStop &&
-      *type != kUwMacaroonCaveatTypeScope &&
-      *type != kUwMacaroonCaveatTypeIdentifier &&
-      *type != kUwMacaroonCaveatTypeIssued &&
-      *type != kUwMacaroonCaveatTypeTTL &&
-      *type != kUwMacaroonCaveatTypeExpiration &&
-      *type != kUwMacaroonCaveatTypeSessionIdentifier) {
+/* === Some internal functions defined in macaroon_caveat_internal.h === */
+
+bool 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) {
+  if (key == NULL || key_len == 0 || context == NULL || caveat == NULL ||
+      mac_tag == NULL || mac_tag_size == 0) {
     return false;
   }
 
+  UwMacaroonCaveatType caveat_type;
+  if (!uw_macaroon_caveat_get_type_(caveat, &caveat_type) ||
+      !is_valid_caveat_type_(caveat_type)) {
+    return false;
+  }
+
+  // Need to encode the whole caveat as a byte string and then sign it
+
+  // If there is no additional value from the context, just compute the HMAC on
+  // the current byte string.
+  uint8_t bstr_cbor_prefix[UW_MACAROON_ENCODING_MAX_UINT_CBOR_LEN] = {0};
+  size_t bstr_cbor_prefix_len = 0;
+  if (caveat_type != kUwMacaroonCaveatTypeBleSessionID) {
+    if (!uw_macaroon_encoding_encode_byte_str_len_(
+            (uint32_t)(caveat->num_bytes), bstr_cbor_prefix,
+            sizeof(bstr_cbor_prefix), &bstr_cbor_prefix_len)) {
+      return false;
+    }
+
+    UwCryptoHmacMsg messages[] = {
+        {bstr_cbor_prefix, bstr_cbor_prefix_len},
+        {caveat->bytes, caveat->num_bytes},
+    };
+
+    return uw_crypto_hmac_(key, key_len, messages,
+                           sizeof(messages) / sizeof(messages[0]), mac_tag,
+                           mac_tag_size);
+  }
+
+  // If there is additional value from the context.
+  if (context->ble_session_id == NULL || context->ble_session_id_len == 0) {
+    return false;
+  }
+
+  // The length here includes the length of the BLE session ID string.
+  if (!uw_macaroon_encoding_encode_byte_str_len_(
+          (uint32_t)(context->ble_session_id_len + caveat->num_bytes),
+          bstr_cbor_prefix, sizeof(bstr_cbor_prefix), &bstr_cbor_prefix_len)) {
+    return false;
+  }
+
+  uint8_t value_cbor_prefix[UW_MACAROON_ENCODING_MAX_UINT_CBOR_LEN] = {0};
+  size_t value_cbor_prefix_len = 0;
+  if (!uw_macaroon_encoding_encode_byte_str_len_(
+          (uint32_t)(context->ble_session_id_len), value_cbor_prefix,
+          sizeof(value_cbor_prefix), &value_cbor_prefix_len)) {
+    return false;
+  }
+
+  UwCryptoHmacMsg messages[] = {
+      {bstr_cbor_prefix, bstr_cbor_prefix_len},
+      {caveat->bytes, caveat->num_bytes},
+      {value_cbor_prefix, value_cbor_prefix_len},
+      {context->ble_session_id, context->ble_session_id_len},
+  };
+
+  return uw_crypto_hmac_(key, key_len, messages,
+                         sizeof(messages) / sizeof(messages[0]), mac_tag,
+                         mac_tag_size);
+}
+
+static bool update_and_check_expiration_time(
+    uint32_t current_time,
+    uint32_t new_expiration_time,
+    UwMacaroonValidationResult* result) {
+  if (result->expiration_time > new_expiration_time) {
+    result->expiration_time = new_expiration_time;
+  }
+
+  return current_time <= result->expiration_time;
+}
+
+static bool update_delegatee_list(UwMacaroonCaveatType caveat_type,
+                                  const UwMacaroonCaveat* caveat,
+                                  UwMacaroonValidationResult* result) {
+  if (result->num_delegatees >= MAX_NUM_DELEGATEES) {
+    return false;
+  }
+  bool is_app = (caveat_type == kUwMacaroonCaveatTypeDelegateeApp);
+
+  if (is_app) {
+    for (size_t i = 0; i < result->num_delegatees; i++) {
+      // There must have at most one DelegateeApp
+      if (result->delegatees[i].is_app) {
+        return false;
+      }
+    }
+  }
+
+  if (!uw_macaroon_caveat_get_value_bstr_(
+          caveat, &(result->delegatees[result->num_delegatees].id),
+          &(result->delegatees[result->num_delegatees].id_len))) {
+    return false;
+  }
+  result->delegatees[result->num_delegatees].is_app = is_app;
+  result->num_delegatees++;
   return true;
 }
 
+bool uw_macaroon_caveat_validate_(const UwMacaroonCaveat* caveat,
+                                  const UwMacaroonContext* context,
+                                  UwMacaroonValidationState* state,
+                                  UwMacaroonValidationResult* result) {
+  if (caveat == NULL || context == NULL || state == NULL || result == NULL) {
+    return false;
+  }
+
+  uint32_t expiration_time = 0;
+  uint32_t issued_time = 0;
+  uint32_t scope = UW_MACAROON_CAVEAT_SCOPE_LOWEST_POSSIBLE;
+
+  UwMacaroonCaveatType caveat_type;
+  if (!uw_macaroon_caveat_get_type_(caveat, &caveat_type)) {
+    return false;
+  }
+
+  switch (caveat_type) {
+    // The types that always validate
+    case kUwMacaroonCaveatTypeClientAuthorizationTokenV1:
+    case kUwMacaroonCaveatTypeServerAuthenticationTokenV1:
+    case kUwMacaroonCaveatTypeNonce:
+    case kUwMacaroonCaveatTypeBleSessionID:
+      return true;
+
+    case kUwMacaroonCaveatTypeDelegationTimestamp:
+      state->has_issued_time = true;
+      if (!uw_macaroon_caveat_get_value_uint_(caveat, &issued_time)) {
+        return false;
+      }
+      state->issued_time = issued_time;
+      return true;
+
+    case kUwMacaroonCaveatTypeTTL1Hour:
+      if (!(state->has_issued_time)) {
+        return false;
+      }
+      return update_and_check_expiration_time(
+          context->current_time, state->issued_time + 60 * 60, result);
+
+    case kUwMacaroonCaveatTypeTTL24Hour:
+      if (!(state->has_issued_time)) {
+        return false;
+      }
+      return update_and_check_expiration_time(
+          context->current_time, state->issued_time + 24 * 60 * 60, result);
+
+    // Need to create a list of delegatees
+    case kUwMacaroonCaveatTypeDelegateeUser:
+      return update_delegatee_list(caveat_type, caveat, result);
+
+    case kUwMacaroonCaveatTypeDelegateeApp:
+      return update_delegatee_list(caveat_type, caveat, result);
+
+    // Time related caveats
+    case kUwMacaroonCaveatTypeExpirationAbsolute:
+      if (!uw_macaroon_caveat_get_value_uint_(caveat, &expiration_time)) {
+        return false;
+      }
+      return update_and_check_expiration_time(context->current_time,
+                                              expiration_time, result);
+
+    // The caveats that update the values of the result object
+    case kUwMacaroonCaveatTypeScope:
+      if (!uw_macaroon_caveat_get_value_uint_(caveat, &scope) ||
+          // Larger value means less priviledge
+          scope < UW_MACAROON_CAVEAT_SCOPE_HIGHEST_POSSIBLE ||
+          scope > UW_MACAROON_CAVEAT_SCOPE_LOWEST_POSSIBLE) {
+        return false;
+      }
+      if (scope > (uint32_t)(result->granted_scope)) {
+        result->granted_scope = (UwMacaroonCaveatScopeType)scope;
+      }
+      return true;
+
+    case kUwMacaroonCaveatTypeAppCommandsOnly:
+      result->weave_app_restricted = true;
+      return true;
+
+    case kUwMacaroonCaveatTypeLanSessionID:
+      return uw_macaroon_caveat_get_value_bstr_(
+          caveat, &(result->lan_session_id), &(result->lan_session_id_len));
+  }
+
+  return false;
+}
+
 bool uw_macaroon_caveat_get_value_uint_(const UwMacaroonCaveat* caveat,
                                         uint32_t* unsigned_int) {
   if (caveat == NULL || unsigned_int == NULL) {
@@ -162,13 +512,13 @@
     return false;
   }
   if (type != kUwMacaroonCaveatTypeScope &&
-      type != kUwMacaroonCaveatTypeIssued &&
-      type != kUwMacaroonCaveatTypeTTL &&
-      type != kUwMacaroonCaveatTypeExpiration) {
+      type != kUwMacaroonCaveatTypeExpirationAbsolute &&
+      type != kUwMacaroonCaveatTypeDelegationTimestamp) {
     // Wrong type
     return false;
   }
 
+  // Skip the portion for CBOR type
   size_t offset;
   if (!uw_macaroon_encoding_get_item_len_(caveat->bytes, caveat->num_bytes,
                                           &offset)) {
@@ -179,8 +529,9 @@
       caveat->bytes + offset, caveat->num_bytes - offset, unsigned_int);
 }
 
-bool uw_macaroon_caveat_get_value_str_(const UwMacaroonCaveat* caveat,
-                                       const uint8_t** str, size_t* str_len) {
+bool uw_macaroon_caveat_get_value_bstr_(const UwMacaroonCaveat* caveat,
+                                        const uint8_t** str,
+                                        size_t* str_len) {
   if (caveat == NULL || str == NULL || str_len == NULL) {
     return false;
   }
@@ -189,7 +540,12 @@
   if (!uw_macaroon_caveat_get_type_(caveat, &type)) {
     return false;
   }
-  if (type != kUwMacaroonCaveatTypeIdentifier) {
+  if (type != kUwMacaroonCaveatTypeNonce &&
+      type != kUwMacaroonCaveatTypeDelegateeUser &&
+      type != kUwMacaroonCaveatTypeDelegateeApp &&
+      type != kUwMacaroonCaveatTypeLanSessionID &&
+      type != kUwMacaroonCaveatTypeClientAuthorizationTokenV1 &&
+      type != kUwMacaroonCaveatTypeServerAuthenticationTokenV1) {
     // Wrong type
     return false;
   }
@@ -200,48 +556,17 @@
     return false;
   }
 
-  return uw_macaroon_encoding_decode_text_str_(
+  return uw_macaroon_encoding_decode_byte_str_(
       caveat->bytes + offset, caveat->num_bytes - offset, str, str_len);
 }
 
-bool uw_macaroon_caveat_sign_(const uint8_t* key, size_t key_len,
-                              const UwMacaroonCaveat* caveat, uint8_t* mac_tag,
-                              size_t mac_tag_size) {
-  if (key == NULL || key_len == 0 || caveat == NULL || mac_tag == NULL ||
-      mac_tag_size == 0) {
+bool uw_macaroon_caveat_init_validation_state_(
+    UwMacaroonValidationState* state) {
+  if (state == NULL) {
     return false;
   }
 
-  uint8_t hmac_state_buffer[HMAC_STATE_BUFFER_SIZE];
-  if (HMAC_STATE_BUFFER_SIZE < uw_crypto_hmac_required_buffer_size_()) {
-    return false;
-  }
-
-  if (!uw_crypto_hmac_init_(hmac_state_buffer, HMAC_STATE_BUFFER_SIZE, key,
-                            key_len)) {
-    return false;
-  }
-
-  if (!uw_crypto_hmac_update_(hmac_state_buffer, HMAC_STATE_BUFFER_SIZE,
-                              caveat->bytes, caveat->num_bytes)) {
-    return false;
-  }
-
-  const uint8_t* context;
-  size_t context_len;
-  UwMacaroonCaveatType caveat_type;
-
-  if ((!uw_macaroon_caveat_get_type_(caveat, &caveat_type)) ||
-      (!uw_macaroon_context_get_(caveat_type, &context, &context_len))) {
-    return false;
-  }
-  if (context != NULL && context_len != 0) {
-    if (!uw_crypto_hmac_update_(hmac_state_buffer, HMAC_STATE_BUFFER_SIZE,
-                                context, context_len)) {
-      return false;
-    }
-  }
-
-  return uw_crypto_hmac_final_(hmac_state_buffer, HMAC_STATE_BUFFER_SIZE,
-                               mac_tag, mac_tag_size);
+  state->has_issued_time = false;
+  state->issued_time = 0;
+  return true;
 }
diff --git a/third_party/libuweave/src/macaroon_caveat.h b/third_party/libuweave/src/macaroon_caveat.h
index 2e01742..9baf70d 100644
--- a/third_party/libuweave/src/macaroon_caveat.h
+++ b/third_party/libuweave/src/macaroon_caveat.h
@@ -15,15 +15,25 @@
 } UwMacaroonCaveat;
 
 typedef enum {
-  kUwMacaroonCaveatTypeStop = 0,
-  kUwMacaroonCaveatTypeScope = 1,
-  kUwMacaroonCaveatTypeIdentifier = 2,
-  kUwMacaroonCaveatTypeIssued = 3,
-  kUwMacaroonCaveatTypeTTL = 4,
-  kUwMacaroonCaveatTypeExpiration = 5,
-  kUwMacaroonCaveatTypeSessionIdentifier = 16,
+  kUwMacaroonCaveatTypeNonce = 0,                            // bstr
+  kUwMacaroonCaveatTypeScope = 1,                            // uint
+  kUwMacaroonCaveatTypeExpirationAbsolute = 5,               // uint
+  kUwMacaroonCaveatTypeTTL1Hour = 6,                         // no value
+  kUwMacaroonCaveatTypeTTL24Hour = 7,                        // no value
+  kUwMacaroonCaveatTypeDelegationTimestamp = 8,              // uint
+  kUwMacaroonCaveatTypeDelegateeUser = 9,                    // bstr
+  kUwMacaroonCaveatTypeDelegateeApp = 10,                    // bstr
+  kUwMacaroonCaveatTypeAppCommandsOnly = 11,                 // no value
+  kUwMacaroonCaveatTypeBleSessionID = 16,                    // no value
+  kUwMacaroonCaveatTypeLanSessionID = 17,                    // bstr
+  kUwMacaroonCaveatTypeClientAuthorizationTokenV1 = 8193,    // bstr (0x2001)
+  kUwMacaroonCaveatTypeServerAuthenticationTokenV1 = 12289,  // bstr (0x3001)
 } UwMacaroonCaveatType;
 
+// For security sanity checks
+#define UW_MACAROON_CAVEAT_SCOPE_HIGHEST_POSSIBLE 0
+#define UW_MACAROON_CAVEAT_SCOPE_LOWEST_POSSIBLE 127
+
 typedef enum {
   kUwMacaroonCaveatScopeTypeOwner = 2,
   kUwMacaroonCaveatScopeTypeManager = 8,
@@ -31,28 +41,75 @@
   kUwMacaroonCaveatScopeTypeViewer = 20,
 } UwMacaroonCaveatScopeType;
 
-bool uw_macaroon_caveat_create_without_value_(UwMacaroonCaveatType type,
+/** Compute the buffer sizes that are enough for caveat creation functions. */
+size_t uw_macaroon_caveat_creation_get_buffsize_(UwMacaroonCaveatType type,
+                                                 size_t str_len);
+
+// Caveat creation functions
+bool uw_macaroon_caveat_create_nonce_(const uint8_t* nonce,
+                                      size_t nonce_size,
+                                      uint8_t* buffer,
+                                      size_t buffer_size,
+                                      UwMacaroonCaveat* new_caveat);
+bool uw_macaroon_caveat_create_scope_(UwMacaroonCaveatScopeType scope,
+                                      uint8_t* buffer,
+                                      size_t buffer_size,
+                                      UwMacaroonCaveat* new_caveat);
+bool uw_macaroon_caveat_create_expiration_absolute_(
+    uint32_t expiration_time,
+    uint8_t* buffer,
+    size_t buffer_size,
+    UwMacaroonCaveat* new_caveat);
+bool uw_macaroon_caveat_create_ttl_1_hour_(uint8_t* buffer,
+                                           size_t buffer_size,
+                                           UwMacaroonCaveat* new_caveat);
+bool uw_macaroon_caveat_create_ttl_24_hour_(uint8_t* buffer,
+                                            size_t buffer_size,
+                                            UwMacaroonCaveat* new_caveat);
+bool uw_macaroon_caveat_create_delegation_timestamp_(
+    uint32_t timestamp,
+    uint8_t* buffer,
+    size_t buffer_size,
+    UwMacaroonCaveat* new_caveat);
+bool 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);
+bool 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);
-bool uw_macaroon_caveat_create_with_uint_(UwMacaroonCaveatType type,
-                                          uint32_t value, uint8_t* buffer,
-                                          size_t buffer_size,
-                                          UwMacaroonCaveat* new_caveat);
-bool uw_macaroon_caveat_create_with_str_(UwMacaroonCaveatType type,
-                                         const uint8_t* str, size_t str_len,
-                                         uint8_t* buffer, size_t buffer_size,
-                                         UwMacaroonCaveat* new_caveat);
+bool uw_macaroon_caveat_create_app_commands_only_(uint8_t* buffer,
+                                                  size_t buffer_size,
+                                                  UwMacaroonCaveat* new_caveat);
+bool uw_macaroon_caveat_create_ble_session_id_(uint8_t* buffer,
+                                               size_t buffer_size,
+                                               UwMacaroonCaveat* new_caveat);
+bool 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);
 
+// The string values for these two token types are optional.
+// Use str_len = 0 to indicate creating the caveats without string values.
+bool 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);
+bool 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);
+
+/** Get the type for the given caveat. */
 bool uw_macaroon_caveat_get_type_(const UwMacaroonCaveat* caveat,
                                   UwMacaroonCaveatType* type);
-bool uw_macaroon_caveat_get_value_uint_(const UwMacaroonCaveat* caveat,
-                                        uint32_t* unsigned_int);
-bool uw_macaroon_caveat_get_value_str_(const UwMacaroonCaveat* caveat,
-                                       const uint8_t** str, size_t* str_len);
-
-bool uw_macaroon_caveat_sign_(const uint8_t* key, size_t key_len,
-                              const UwMacaroonCaveat* caveat, uint8_t* mac_tag,
-                              size_t mac_tag_size);
 
 #endif  // LIBUWEAVE_SRC_MACAROON_CAVEAT_H_
diff --git a/third_party/libuweave/src/macaroon_caveat_internal.h b/third_party/libuweave/src/macaroon_caveat_internal.h
new file mode 100644
index 0000000..46a72fb
--- /dev/null
+++ b/third_party/libuweave/src/macaroon_caveat_internal.h
@@ -0,0 +1,41 @@
+// Copyright 2015 The Weave Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef LIBUWEAVE_SRC_MACAROON_CAVEAT_INTERNAL_H_
+#define LIBUWEAVE_SRC_MACAROON_CAVEAT_INTERNAL_H_
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include "src/macaroon.h"
+#include "src/macaroon_caveat.h"
+
+bool 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);
+
+typedef struct {
+  bool has_issued_time;
+  uint32_t issued_time;
+} UwMacaroonValidationState;
+
+bool uw_macaroon_caveat_init_validation_state_(
+    UwMacaroonValidationState* state);
+
+bool uw_macaroon_caveat_validate_(const UwMacaroonCaveat* caveat,
+                                  const UwMacaroonContext* context,
+                                  UwMacaroonValidationState* state,
+                                  UwMacaroonValidationResult* result);
+
+bool uw_macaroon_caveat_get_value_uint_(const UwMacaroonCaveat* caveat,
+                                        uint32_t* unsigned_int);
+bool uw_macaroon_caveat_get_value_bstr_(const UwMacaroonCaveat* caveat,
+                                        const uint8_t** str,
+                                        size_t* str_len);
+
+#endif  // LIBUWEAVE_SRC_MACAROON_CAVEAT_INTERNAL_H_
diff --git a/third_party/libuweave/src/macaroon_context.c b/third_party/libuweave/src/macaroon_context.c
index 7477784..2f1685d 100644
--- a/third_party/libuweave/src/macaroon_context.c
+++ b/third_party/libuweave/src/macaroon_context.c
@@ -4,19 +4,19 @@
 
 #include "src/macaroon_context.h"
 
-#include "src/macaroon_caveat.h"
-
-bool uw_macaroon_context_get_(UwMacaroonCaveatType type,
-                              const uint8_t** context, size_t* context_len) {
-  if (type != kUwMacaroonCaveatTypeSessionIdentifier) {
-    *context = NULL;
-    *context_len = 0;
+bool uw_macaroon_context_create_(uint32_t current_time,
+                                 const uint8_t* ble_session_id,
+                                 size_t ble_session_id_len,
+                                 UwMacaroonContext* new_context) {
+  if (ble_session_id == NULL && ble_session_id_len != 0) {
+    return false;
+  }
+  if (new_context == NULL) {
+    return false;
   }
 
-  // TODO(bozhu): Waiting for a proper way to obtain the session identifier.
-  // Have we already implemented something related to session identifiers?
-  *context = NULL;
-  *context_len = 0;
-
+  new_context->current_time = current_time;
+  new_context->ble_session_id = ble_session_id;
+  new_context->ble_session_id_len = ble_session_id_len;
   return true;
 }
diff --git a/third_party/libuweave/src/macaroon_context.h b/third_party/libuweave/src/macaroon_context.h
index 8522b69..c230eb7 100644
--- a/third_party/libuweave/src/macaroon_context.h
+++ b/third_party/libuweave/src/macaroon_context.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef UW_LIBUWEAVE_SRC_MACAROON_CONTEXT_
-#define UW_LIBUWEAVE_SRC_MACAROON_CONTEXT_
+#ifndef LIBUWEAVE_SRC_MACAROON_CONTEXT_
+#define LIBUWEAVE_SRC_MACAROON_CONTEXT_
 
 #include <stdbool.h>
 #include <stddef.h>
@@ -11,7 +11,15 @@
 
 #include "src/macaroon_caveat.h"
 
-bool uw_macaroon_context_get_(UwMacaroonCaveatType type,
-                              const uint8_t** context, size_t* context_len);
+typedef struct {
+  uint32_t current_time;  // In number of seconds since Jan 1st 2000 00:00:00
+  const uint8_t* ble_session_id;  // Only for BLE
+  size_t ble_session_id_len;
+} UwMacaroonContext;
 
-#endif  // UW_LIBUWEAVE_SRC_MACAROON_CONTEXT_
+bool uw_macaroon_context_create_(uint32_t current_time,
+                                 const uint8_t* ble_session_id,
+                                 size_t ble_session_id_len,
+                                 UwMacaroonContext* new_context);
+
+#endif  // LIBUWEAVE_SRC_MACAROON_CONTEXT_
diff --git a/third_party/libuweave/src/macaroon_encoding.c b/third_party/libuweave/src/macaroon_encoding.c
index 3fb5323..29adc52 100644
--- a/third_party/libuweave/src/macaroon_encoding.c
+++ b/third_party/libuweave/src/macaroon_encoding.c
@@ -21,28 +21,34 @@
   kCborMajorTypeArray = 4 << 5,    // type 4 -- arrays
 } CborMajorType;
 
-// -- Prototypes begin --
 static inline CborMajorType get_type_(const uint8_t* cbor);
 static inline uint8_t get_addtl_data_(const uint8_t* cbor);
 static inline void set_type_(CborMajorType type, uint8_t* cbor);
 static inline void set_addtl_data_(uint8_t addtl_data, uint8_t* cbor);
 
-// Compute the minimum number of bytes to store the unsigned integer.
+/** Computes the minimum number of bytes to store the unsigned integer. */
 static inline size_t uint_min_len_(uint32_t unsigned_int);
 
-// Encoding or decoding without checking types
-static bool blindly_encode_uint_(uint32_t unsigned_int, uint8_t* buffer,
-                                 size_t buffer_size, size_t* result_len);
-static bool blindly_encode_str_(const uint8_t* str, size_t str_len,
-                                uint8_t* buffer, size_t buffer_size,
+/** Encoding or decoding without checking types */
+static bool blindly_encode_uint_(uint32_t unsigned_int,
+                                 uint8_t* buffer,
+                                 size_t buffer_size,
+                                 size_t* result_len);
+static bool blindly_encode_str_(const uint8_t* str,
+                                size_t str_len,
+                                uint8_t* buffer,
+                                size_t buffer_size,
                                 size_t* result_len);
-static bool blindly_decode_uint_(const uint8_t* cbor, size_t cbor_len,
+static bool blindly_decode_uint_(const uint8_t* cbor,
+                                 size_t cbor_len,
                                  uint32_t* unsigned_int);
-static bool blindly_decode_str_(const uint8_t* cbor, size_t cbor_len,
-                                const uint8_t** out_str, size_t* out_str_len);
-// -- Prototypes end --
+static bool blindly_decode_str_(const uint8_t* cbor,
+                                size_t cbor_len,
+                                const uint8_t** out_str,
+                                size_t* out_str_len);
 
-bool uw_macaroon_encoding_get_item_len_(const uint8_t* cbor, size_t cbor_len,
+bool uw_macaroon_encoding_get_item_len_(const uint8_t* cbor,
+                                        size_t cbor_len,
                                         size_t* first_item_len) {
   if (cbor == NULL || cbor_len == 0 || first_item_len == NULL) {
     return false;
@@ -76,7 +82,8 @@
 }
 
 bool uw_macaroon_encoding_encode_uint_(const uint32_t unsigned_int,
-                                       uint8_t* buffer, size_t buffer_size,
+                                       uint8_t* buffer,
+                                       size_t buffer_size,
                                        size_t* resulting_cbor_len) {
   if (buffer == NULL || buffer_size == 0 || resulting_cbor_len == NULL) {
     return false;
@@ -88,7 +95,8 @@
 }
 
 bool uw_macaroon_encoding_encode_array_len_(const uint32_t array_len,
-                                            uint8_t* buffer, size_t buffer_size,
+                                            uint8_t* buffer,
+                                            size_t buffer_size,
                                             size_t* resulting_cbor_len) {
   if (buffer == NULL || buffer_size == 0 || resulting_cbor_len == NULL) {
     return false;
@@ -99,8 +107,10 @@
                               resulting_cbor_len);
 }
 
-bool uw_macaroon_encoding_encode_byte_str_(const uint8_t* str, size_t str_len,
-                                           uint8_t* buffer, size_t buffer_size,
+bool uw_macaroon_encoding_encode_byte_str_(const uint8_t* str,
+                                           size_t str_len,
+                                           uint8_t* buffer,
+                                           size_t buffer_size,
                                            size_t* resulting_cbor_len) {
   if (buffer == NULL || buffer_size == 0 || resulting_cbor_len == NULL) {
     return false;
@@ -111,8 +121,10 @@
                              resulting_cbor_len);
 }
 
-bool uw_macaroon_encoding_encode_text_str_(const uint8_t* str, size_t str_len,
-                                           uint8_t* buffer, size_t buffer_size,
+bool uw_macaroon_encoding_encode_text_str_(const uint8_t* str,
+                                           size_t str_len,
+                                           uint8_t* buffer,
+                                           size_t buffer_size,
                                            size_t* resulting_cbor_len) {
   if (buffer == NULL || buffer_size == 0 || resulting_cbor_len == NULL) {
     return false;
@@ -123,7 +135,19 @@
                              resulting_cbor_len);
 }
 
-bool uw_macaroon_encoding_decode_uint_(const uint8_t* cbor, size_t cbor_len,
+bool uw_macaroon_encoding_encode_byte_str_len_(size_t str_len,
+                                               uint8_t* buffer,
+                                               size_t buffer_size,
+                                               size_t* resulting_cbor_len) {
+  if (buffer == NULL || buffer_size == 0 || resulting_cbor_len == NULL) {
+    return false;
+  }
+  set_type_(kCborMajorTypeByteStr, buffer);
+  return blindly_encode_uint_(str_len, buffer, buffer_size, resulting_cbor_len);
+}
+
+bool uw_macaroon_encoding_decode_uint_(const uint8_t* cbor,
+                                       size_t cbor_len,
                                        uint32_t* unsigned_int) {
   if (cbor == NULL || cbor_len == 0 || unsigned_int == NULL ||
       get_type_(cbor) != kCborMajorTypeUint) {
@@ -144,7 +168,8 @@
   return blindly_decode_uint_(cbor, cbor_len, array_len);
 }
 
-bool uw_macaroon_encoding_decode_byte_str_(const uint8_t* cbor, size_t cbor_len,
+bool uw_macaroon_encoding_decode_byte_str_(const uint8_t* cbor,
+                                           size_t cbor_len,
                                            const uint8_t** out_str,
                                            size_t* out_str_len) {
   if (cbor == NULL || cbor_len == 0 || out_str == NULL || out_str_len == NULL ||
@@ -155,7 +180,8 @@
   return blindly_decode_str_(cbor, cbor_len, out_str, out_str_len);
 }
 
-bool uw_macaroon_encoding_decode_text_str_(const uint8_t* cbor, size_t cbor_len,
+bool uw_macaroon_encoding_decode_text_str_(const uint8_t* cbor,
+                                           size_t cbor_len,
                                            const uint8_t** out_str,
                                            size_t* out_str_len) {
   if (cbor == NULL || cbor_len == 0 || out_str == NULL || out_str_len == NULL ||
@@ -193,9 +219,12 @@
   return 4;
 }
 
-// Write the unsigned int in the big-endian fashion by using the minimum number
-// of bytes in CBOR
-static inline bool write_uint_big_endian_(uint32_t unsigned_int, uint8_t* buff,
+/**
+ * Writes the unsigned int in the big-endian fashion by using the minimum number
+ * of bytes in CBOR
+ */
+static inline bool write_uint_big_endian_(uint32_t unsigned_int,
+                                          uint8_t* buff,
                                           size_t buff_len) {
   if (buff == NULL || buff_len == 0) {
     return false;
@@ -225,8 +254,9 @@
   return true;
 }
 
-// Read the unsigned int written in big-endian
-static inline bool read_uint_big_endian_(const uint8_t* bytes, size_t num_bytes,
+/** Reads the unsigned int written in big-endian. */
+static inline bool read_uint_big_endian_(const uint8_t* bytes,
+                                         size_t num_bytes,
                                          uint32_t* unsigned_int) {
   if (bytes == NULL || num_bytes == 0 || num_bytes > 4 ||
       unsigned_int == NULL) {
@@ -252,8 +282,10 @@
   return true;
 }
 
-static bool blindly_encode_uint_(uint32_t unsigned_int, uint8_t* buffer,
-                                 size_t buffer_size, size_t* result_len) {
+static bool blindly_encode_uint_(uint32_t unsigned_int,
+                                 uint8_t* buffer,
+                                 size_t buffer_size,
+                                 size_t* result_len) {
   if (buffer == NULL || buffer_size == 0 || result_len == NULL) {
     return false;
   }
@@ -288,8 +320,10 @@
   return write_uint_big_endian_(unsigned_int, buffer + 1, buffer_size - 1);
 }
 
-static bool blindly_encode_str_(const uint8_t* str, size_t str_len,
-                                uint8_t* buffer, size_t buffer_size,
+static bool blindly_encode_str_(const uint8_t* str,
+                                size_t str_len,
+                                uint8_t* buffer,
+                                size_t buffer_size,
                                 size_t* result_len) {
   if (buffer == NULL || buffer_size == 0) {
     return false;
@@ -320,7 +354,8 @@
   return true;
 }
 
-static bool blindly_decode_uint_(const uint8_t* cbor, size_t cbor_len,
+static bool blindly_decode_uint_(const uint8_t* cbor,
+                                 size_t cbor_len,
                                  uint32_t* unsigned_int) {
   if (cbor == NULL || cbor_len == 0 || unsigned_int == NULL) {
     return false;
@@ -344,8 +379,10 @@
   return read_uint_big_endian_(cbor + 1, uint_num_bytes, unsigned_int);
 }
 
-static bool blindly_decode_str_(const uint8_t* cbor, size_t cbor_len,
-                                const uint8_t** out_str, size_t* out_str_len) {
+static bool blindly_decode_str_(const uint8_t* cbor,
+                                size_t cbor_len,
+                                const uint8_t** out_str,
+                                size_t* out_str_len) {
   if (cbor == NULL || cbor_len == 0 || out_str == NULL || out_str == NULL) {
     return false;
   }
diff --git a/third_party/libuweave/src/macaroon_encoding.h b/third_party/libuweave/src/macaroon_encoding.h
index edddfc1..60f80a6 100644
--- a/third_party/libuweave/src/macaroon_encoding.h
+++ b/third_party/libuweave/src/macaroon_encoding.h
@@ -17,32 +17,53 @@
 #include <stddef.h>
 #include <stdint.h>
 
-// Get the number of bytes that is occupied by the first data item in the give
-// CBOR string.
-bool uw_macaroon_encoding_get_item_len_(const uint8_t* cbor, size_t cbor_len,
+#define UW_MACAROON_ENCODING_MAX_UINT_CBOR_LEN 5
+
+/**
+ * Gets the number of bytes that is occupied by the first data item in the give
+ * CBOR string.
+ */
+bool uw_macaroon_encoding_get_item_len_(const uint8_t* cbor,
+                                        size_t cbor_len,
                                         size_t* first_item_len);
 
 bool uw_macaroon_encoding_encode_uint_(const uint32_t unsigned_int,
-                                       uint8_t* buffer, size_t buffer_size,
+                                       uint8_t* buffer,
+                                       size_t buffer_size,
                                        size_t* resulting_cbor_len);
 bool uw_macaroon_encoding_encode_array_len_(const uint32_t array_len,
-                                            uint8_t* buffer, size_t buffer_size,
+                                            uint8_t* buffer,
+                                            size_t buffer_size,
                                             size_t* resulting_cbor_len);
-bool uw_macaroon_encoding_encode_byte_str_(const uint8_t* str, size_t str_len,
-                                           uint8_t* buffer, size_t buffer_size,
+bool uw_macaroon_encoding_encode_byte_str_(const uint8_t* str,
+                                           size_t str_len,
+                                           uint8_t* buffer,
+                                           size_t buffer_size,
                                            size_t* resulting_cbor_len);
-bool uw_macaroon_encoding_encode_text_str_(const uint8_t* str, size_t str_len,
-                                           uint8_t* buffer, size_t buffer_size,
+bool uw_macaroon_encoding_encode_text_str_(const uint8_t* str,
+                                           size_t str_len,
+                                           uint8_t* buffer,
+                                           size_t buffer_size,
                                            size_t* resulting_cbor_len);
 
-bool uw_macaroon_encoding_decode_uint_(const uint8_t* cbor, size_t cbor_len,
+/** Only encode the header (major type and length) of the byte string */
+bool uw_macaroon_encoding_encode_byte_str_len_(size_t str_len,
+                                               uint8_t* buffer,
+                                               size_t buffer_size,
+                                               size_t* resulting_cbor_len);
+
+bool uw_macaroon_encoding_decode_uint_(const uint8_t* cbor,
+                                       size_t cbor_len,
                                        uint32_t* unsigned_int);
 bool uw_macaroon_encoding_decode_array_len_(const uint8_t* cbor,
-                                            size_t cbor_len, uint32_t* array_len);
-bool uw_macaroon_encoding_decode_byte_str_(const uint8_t* cbor, size_t cbor_len,
+                                            size_t cbor_len,
+                                            uint32_t* array_len);
+bool uw_macaroon_encoding_decode_byte_str_(const uint8_t* cbor,
+                                           size_t cbor_len,
                                            const uint8_t** str,
                                            size_t* str_len);
-bool uw_macaroon_encoding_decode_text_str_(const uint8_t* cbor, size_t cbor_len,
+bool uw_macaroon_encoding_decode_text_str_(const uint8_t* cbor,
+                                           size_t cbor_len,
                                            const uint8_t** str,
                                            size_t* str_len);