Update macaroon library

Change-Id: Ib4d46c103b1fe9c9c21fa55e06e1cc894fcd8efd
Reviewed-on: https://weave-review.googlesource.com/1843
Reviewed-by: Vitaly Buka <vitalybuka@google.com>
diff --git a/third_party/libuweave/src/macaroon.c b/third_party/libuweave/src/macaroon.c
index d7e6491..70afda1 100644
--- a/third_party/libuweave/src/macaroon.c
+++ b/third_party/libuweave/src/macaroon.c
@@ -7,6 +7,8 @@
 #include <string.h>
 
 #include "src/crypto_utils.h"
+#include "src/macaroon_caveat.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,
@@ -124,3 +126,94 @@
   return create_mac_tag_(old_macaroon->mac_tag, UW_MACAROON_MAC_LEN,
                          additional_caveat, 1, new_macaroon->mac_tag);
 }
+
+// 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 ||
+      resulting_str_len == NULL) {
+    return false;
+  }
+
+  size_t offset = 0, item_len;
+
+  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)) {
+    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,
+            out + offset, out_len - offset, &item_len)) {
+      return false;
+    }
+    offset += item_len;
+  }
+
+  *resulting_str_len = offset;
+  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) {
+    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) {
+    return false;
+  }
+  memcpy(macaroon->mac_tag, tag, UW_MACAROON_MAC_LEN);
+
+  size_t offset = 0, cbor_item_len;
+  if (!uw_macaroon_encoding_get_item_len_(in, in_len, &cbor_item_len)) {
+    return false;
+  }
+  offset += cbor_item_len;
+
+  uint32_t array_len;
+  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)) {
+    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;
+    }
+  }
+  macaroon->caveats = caveats;
+
+  return true;
+}
diff --git a/third_party/libuweave/src/macaroon.h b/third_party/libuweave/src/macaroon.h
index 98ada11..61242f7 100644
--- a/third_party/libuweave/src/macaroon.h
+++ b/third_party/libuweave/src/macaroon.h
@@ -44,4 +44,21 @@
                          const UwMacaroonCaveat* additional_caveat,
                          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);
+
+// 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);
+
 #endif  // LIBUWEAVE_SRC_MACAROON_H_
diff --git a/third_party/libuweave/src/macaroon_encoding.c b/third_party/libuweave/src/macaroon_encoding.c
index 214314d..3fb5323 100644
--- a/third_party/libuweave/src/macaroon_encoding.c
+++ b/third_party/libuweave/src/macaroon_encoding.c
@@ -15,9 +15,10 @@
 // #define FLAG_8BYTE_UINT 27  // Do not support 8-byte
 
 typedef enum {
-  kCborMajorTypeUint = 0,          // type 0
-  kCborMajorTypeByteStr = 2 << 5,  // type 2
-  kCborMajorTypeTextStr = 3 << 5,  // type 3
+  kCborMajorTypeUint = 0,          // type 0 -- unsigned integers
+  kCborMajorTypeByteStr = 2 << 5,  // type 2 -- byte strings
+  kCborMajorTypeTextStr = 3 << 5,  // type 3 -- text strings
+  kCborMajorTypeArray = 4 << 5,    // type 4 -- arrays
 } CborMajorType;
 
 // -- Prototypes begin --
@@ -49,7 +50,7 @@
 
   CborMajorType type = get_type_(cbor);
   if (type != kCborMajorTypeUint && type != kCborMajorTypeByteStr &&
-      type != kCborMajorTypeTextStr) {
+      type != kCborMajorTypeTextStr && type != kCborMajorTypeArray) {
     // Other types are not supported
     return false;
   }
@@ -61,6 +62,8 @@
 
   *first_item_len = uint_min_len_(unsigned_int) + 1;
 
+  // For arrays, it returns only the length of the array length portion, not the
+  // length of the whole array
   if (type == kCborMajorTypeByteStr || type == kCborMajorTypeTextStr) {
     *first_item_len += (size_t)unsigned_int;
   }
@@ -84,6 +87,18 @@
                               resulting_cbor_len);
 }
 
+bool uw_macaroon_encoding_encode_array_len_(const uint32_t array_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_(kCborMajorTypeArray, buffer);
+  return blindly_encode_uint_(array_len, buffer, buffer_size,
+                              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,
                                            size_t* resulting_cbor_len) {
@@ -110,27 +125,30 @@
 
 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) {
-    return false;
-  }
-
-  CborMajorType type = get_type_(cbor);
-  if (type != kCborMajorTypeUint) {
+  if (cbor == NULL || cbor_len == 0 || unsigned_int == NULL ||
+      get_type_(cbor) != kCborMajorTypeUint) {
     return false;
   }
 
   return blindly_decode_uint_(cbor, cbor_len, unsigned_int);
 }
 
-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) {
+bool uw_macaroon_encoding_decode_array_len_(const uint8_t* cbor,
+                                            size_t cbor_len,
+                                            uint32_t* array_len) {
+  if (cbor == NULL || cbor_len == 0 || array_len == NULL ||
+      get_type_(cbor) != kCborMajorTypeArray) {
     return false;
   }
 
-  CborMajorType type = get_type_(cbor);
-  if (type != kCborMajorTypeByteStr) {
+  return blindly_decode_uint_(cbor, cbor_len, array_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 ||
+      get_type_(cbor) != kCborMajorTypeByteStr) {
     return false;
   }
 
@@ -140,12 +158,8 @@
 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) {
-    return false;
-  }
-
-  CborMajorType type = get_type_(cbor);
-  if (type != kCborMajorTypeTextStr) {
+  if (cbor == NULL || cbor_len == 0 || out_str == NULL || out_str_len == NULL ||
+      get_type_(cbor) != kCborMajorTypeTextStr) {
     return false;
   }
 
diff --git a/third_party/libuweave/src/macaroon_encoding.h b/third_party/libuweave/src/macaroon_encoding.h
index 2c11fd1..edddfc1 100644
--- a/third_party/libuweave/src/macaroon_encoding.h
+++ b/third_party/libuweave/src/macaroon_encoding.h
@@ -10,7 +10,7 @@
  * cryptographic use, such as signatures. We only need to support a very small
  * subset of the CBOR standard, since only these are used in our cryptographic
  * designs. The supported data types are: unsigned integers (maximum 32 bits),
- * byte strings, and text strings.
+ * byte strings, text strings, and arrays.
  */
 
 #include <stdbool.h>
@@ -25,6 +25,9 @@
 bool uw_macaroon_encoding_encode_uint_(const uint32_t unsigned_int,
                                        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,
+                                            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,
                                            size_t* resulting_cbor_len);
@@ -34,6 +37,8 @@
 
 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,
                                            const uint8_t** str,
                                            size_t* str_len);