aboutsummaryrefslogtreecommitdiff
path: root/third_party/libuweave/src
diff options
context:
space:
mode:
authorVitaly Buka <vitalybuka@google.com>2016-02-06 01:13:28 +0000
committerandroid-build-merger <android-build-merger@google.com>2016-02-06 01:13:28 +0000
commit18bf9157ffe51f8715c39da2fb443585d0e80a19 (patch)
tree5f4c54a2c23bfd547d32b8c02dbfef5324ea9db6 /third_party/libuweave/src
parenta7aeba920089e43c38578f1fe72ed32dc9e5bc98 (diff)
parentee286963b220f3049aa5f8834c4c7d25d1fc3cd8 (diff)
downloadlibweave-7cc68e7666258ff6080dd511cd56f34bbcc1e935.tar.gz
Merge remote-tracking branch \'weave/master\' into \'weave/aosp-master\' am: d69c671dd4android-cts_7.1_r1android-cts-7.1_r9android-cts-7.1_r8android-cts-7.1_r7android-cts-7.1_r6android-cts-7.1_r5android-cts-7.1_r4android-cts-7.1_r3android-cts-7.1_r29android-cts-7.1_r28android-cts-7.1_r27android-cts-7.1_r26android-cts-7.1_r25android-cts-7.1_r24android-cts-7.1_r23android-cts-7.1_r22android-cts-7.1_r21android-cts-7.1_r20android-cts-7.1_r2android-cts-7.1_r19android-cts-7.1_r18android-cts-7.1_r17android-cts-7.1_r16android-cts-7.1_r15android-cts-7.1_r14android-cts-7.1_r13android-cts-7.1_r12android-cts-7.1_r11android-cts-7.1_r10android-cts-7.1_r1android-7.1.2_r9android-7.1.2_r8android-7.1.2_r6android-7.1.2_r5android-7.1.2_r4android-7.1.2_r39android-7.1.2_r38android-7.1.2_r37android-7.1.2_r36android-7.1.2_r33android-7.1.2_r32android-7.1.2_r30android-7.1.2_r3android-7.1.2_r29android-7.1.2_r28android-7.1.2_r27android-7.1.2_r25android-7.1.2_r24android-7.1.2_r23android-7.1.2_r2android-7.1.2_r19android-7.1.2_r18android-7.1.2_r17android-7.1.2_r16android-7.1.2_r15android-7.1.2_r14android-7.1.2_r13android-7.1.2_r12android-7.1.2_r11android-7.1.2_r10android-7.1.2_r1android-7.1.1_r9android-7.1.1_r8android-7.1.1_r7android-7.1.1_r61android-7.1.1_r60android-7.1.1_r6android-7.1.1_r59android-7.1.1_r58android-7.1.1_r57android-7.1.1_r56android-7.1.1_r55android-7.1.1_r54android-7.1.1_r53android-7.1.1_r52android-7.1.1_r51android-7.1.1_r50android-7.1.1_r49android-7.1.1_r48android-7.1.1_r47android-7.1.1_r46android-7.1.1_r45android-7.1.1_r44android-7.1.1_r43android-7.1.1_r42android-7.1.1_r41android-7.1.1_r40android-7.1.1_r4android-7.1.1_r39android-7.1.1_r38android-7.1.1_r35android-7.1.1_r33android-7.1.1_r32android-7.1.1_r31android-7.1.1_r3android-7.1.1_r28android-7.1.1_r27android-7.1.1_r26android-7.1.1_r25android-7.1.1_r24android-7.1.1_r23android-7.1.1_r22android-7.1.1_r21android-7.1.1_r20android-7.1.1_r2android-7.1.1_r17android-7.1.1_r16android-7.1.1_r15android-7.1.1_r14android-7.1.1_r13android-7.1.1_r12android-7.1.1_r11android-7.1.1_r10android-7.1.1_r1android-7.1.0_r7android-7.1.0_r6android-7.1.0_r5android-7.1.0_r4android-7.1.0_r3android-7.1.0_r2android-7.1.0_r1nougat-mr2.3-releasenougat-mr2.2-releasenougat-mr2.1-releasenougat-mr2-security-releasenougat-mr2-releasenougat-mr2-pixel-releasenougat-mr2-devnougat-mr1.8-releasenougat-mr1.7-releasenougat-mr1.6-releasenougat-mr1.5-releasenougat-mr1.4-releasenougat-mr1.3-releasenougat-mr1.2-releasenougat-mr1.1-releasenougat-mr1-volantis-releasenougat-mr1-security-releasenougat-mr1-releasenougat-mr1-flounder-releasenougat-mr1-devnougat-mr1-cts-releasenougat-dr1-releasenougat-dev
am: ee286963b2 * commit 'ee286963b220f3049aa5f8834c4c7d25d1fc3cd8': (27 commits) Fix some libevhtp usage details. libevhtp requires libevent-dev Add customizable settings option for xmpp_endpoint cmake is used to build gtest and libevhtp Update libuweave/macaroon code Revert "Make internal googletest optional." Fix incorrect weave setting file path Make internal googletest optional. Make internal libevhtp optional. Fix GCC warning Make App ID a part of User ID Update macaroon lib with version supporting empty strings Remove unused line Add kUwMacaroonDelegateeTypeService caveat Add session ID validation Remove crypto type "None" Update macaroon lib Integrate new macaroon library Update macaroon lib Fix build errors introduced by ...
Diffstat (limited to 'third_party/libuweave/src')
-rw-r--r--third_party/libuweave/src/crypto_hmac.c51
-rw-r--r--third_party/libuweave/src/crypto_hmac.h30
-rw-r--r--third_party/libuweave/src/crypto_utils.c7
-rw-r--r--third_party/libuweave/src/macaroon.c289
-rw-r--r--third_party/libuweave/src/macaroon.h98
-rw-r--r--third_party/libuweave/src/macaroon_caveat.c620
-rw-r--r--third_party/libuweave/src/macaroon_caveat.h112
-rw-r--r--third_party/libuweave/src/macaroon_caveat_internal.h40
-rw-r--r--third_party/libuweave/src/macaroon_context.c24
-rw-r--r--third_party/libuweave/src/macaroon_context.h18
-rw-r--r--third_party/libuweave/src/macaroon_encoding.c103
-rw-r--r--third_party/libuweave/src/macaroon_encoding.h47
12 files changed, 1038 insertions, 401 deletions
diff --git a/third_party/libuweave/src/crypto_hmac.c b/third_party/libuweave/src/crypto_hmac.c
index 8b75133..d3dca65 100644
--- a/third_party/libuweave/src/crypto_hmac.c
+++ b/third_party/libuweave/src/crypto_hmac.c
@@ -11,41 +11,24 @@
#include <openssl/evp.h>
#include <openssl/hmac.h>
-size_t uw_crypto_hmac_required_buffer_size_() {
- return sizeof(HMAC_CTX);
-}
-
-bool uw_crypto_hmac_init_(uint8_t* state_buffer,
- size_t state_buffer_len,
- const uint8_t* key,
- size_t key_len) {
- if (sizeof(HMAC_CTX) > state_buffer_len) {
+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) {
+ HMAC_CTX context = {0};
+ HMAC_CTX_init(&context);
+ if (!HMAC_Init(&context, key, key_len, EVP_sha256()))
return false;
- }
- HMAC_CTX* context = (HMAC_CTX*)state_buffer;
- HMAC_CTX_init(context);
- return HMAC_Init(context, key, key_len, EVP_sha256());
-}
-bool uw_crypto_hmac_update_(uint8_t* state_buffer,
- size_t state_buffer_len,
- const uint8_t* data,
- size_t data_len) {
- if (sizeof(HMAC_CTX) > state_buffer_len) {
- return false;
- }
- HMAC_CTX* context = (HMAC_CTX*)state_buffer;
- return HMAC_Update(context, data, 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) {
- if (sizeof(HMAC_CTX) > state_buffer_len) {
- return false;
+ for (size_t i = 0; i < num_messages; ++i) {
+ if (messages[i].num_bytes &&
+ (!messages[i].bytes ||
+ !HMAC_Update(&context, messages[i].bytes, messages[i].num_bytes))) {
+ return false;
+ }
}
- HMAC_CTX* context = (HMAC_CTX*)state_buffer;
const size_t kFullDigestLen = (size_t)EVP_MD_size(EVP_sha256());
if (truncated_digest_len > kFullDigestLen) {
@@ -55,8 +38,8 @@ bool uw_crypto_hmac_final_(uint8_t* state_buffer,
uint8_t digest[kFullDigestLen];
uint32_t len = kFullDigestLen;
- bool result = HMAC_Final(context, digest, &len) && kFullDigestLen == len;
- HMAC_CTX_cleanup(context);
+ bool result = HMAC_Final(&context, digest, &len) && kFullDigestLen == len;
+ HMAC_CTX_cleanup(&context);
if (result) {
memcpy(truncated_digest, digest, truncated_digest_len);
}
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..c823804 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 @@ static bool create_mac_tag_(const uint8_t* key, size_t key_len,
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 @@ static bool create_mac_tag_(const uint8_t* key, size_t key_len,
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,231 @@ bool uw_macaroon_new_from_root_key_(UwMacaroon* new_macaroon,
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);
}
-// 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) {
+static void init_validation_result(UwMacaroonValidationResult* result) {
+ // Start from the largest scope
+ *result = (UwMacaroonValidationResult){
+ .granted_scope = kUwMacaroonCaveatScopeTypeOwner,
+ .expiration_time = UINT32_MAX,
+ };
+}
+
+/** Reset the result object to the lowest scope when encountering errors */
+static void reset_validation_result(UwMacaroonValidationResult* result) {
+ *result = (UwMacaroonValidationResult){
+ .weave_app_restricted = true,
+ .granted_scope = UW_MACAROON_CAVEAT_SCOPE_LOWEST_POSSIBLE};
+}
+
+/** Get the next closest scope (to the narrower side). */
+static UwMacaroonCaveatScopeType get_closest_scope(
+ UwMacaroonCaveatScopeType scope) {
+ if (scope <= kUwMacaroonCaveatScopeTypeOwner) {
+ return kUwMacaroonCaveatScopeTypeOwner;
+ } else if (scope <= kUwMacaroonCaveatScopeTypeManager) {
+ return kUwMacaroonCaveatScopeTypeManager;
+ } else if (scope <= kUwMacaroonCaveatScopeTypeUser) {
+ return kUwMacaroonCaveatScopeTypeUser;
+ } else if (scope <= kUwMacaroonCaveatScopeTypeViewer) {
+ return kUwMacaroonCaveatScopeTypeViewer;
+ }
+ return scope;
+}
+
+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);
- size_t offset = 0, item_len;
+ 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;
+ }
- if (!uw_macaroon_encoding_encode_byte_str_(
- macaroon->mac_tag, UW_MACAROON_MAC_LEN, out, out_len, &item_len)) {
+ UwMacaroonValidationState state;
+ if (!uw_macaroon_caveat_init_validation_state_(&state)) {
return false;
}
- offset += item_len;
+ 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;
+ }
+ }
+
+ result->granted_scope = get_closest_scope(result->granted_scope);
+ return true;
+}
- if (!uw_macaroon_encoding_encode_array_len_(
- (uint32_t)(macaroon->num_caveats), out + offset, out_len - offset, &item_len)) {
+// 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) {
+ if (macaroon == NULL || out == NULL ||
+ out_len < UW_MACAROON_ENCODING_MAX_UINT_CBOR_LEN ||
+ resulting_str_len == NULL) {
+ return false;
+ }
+
+ // Need to encode the whole Macaroon again into a byte string.
+
+ // 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;
+ }
+
+ if (!uw_macaroon_encoding_get_item_len_(in + offset, in_len - offset,
+ &item_len)) {
return false;
}
+ offset += item_len;
- UwMacaroonCaveat* caveats = (UwMacaroonCaveat*)caveats_buffer;
+ 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++) {
- if (!uw_macaroon_encoding_get_item_len_(in + offset, in_len - offset,
- &cbor_item_len)) {
+ 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;
}
- offset += cbor_item_len;
- if (!uw_macaroon_encoding_decode_byte_str_(in + offset, in_len - offset,
- &(caveats[i].bytes),
- &(caveats[i].num_bytes))) {
+ 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;
}
- macaroon->caveats = caveats;
+ 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..c739bca 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,80 @@
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 enum {
+ kUwMacaroonDelegateeTypeNone = 0,
+ kUwMacaroonDelegateeTypeUser = 1,
+ kUwMacaroonDelegateeTypeApp = 2,
+ kUwMacaroonDelegateeTypeService = 3,
+} UwMacaroonDelegateeType;
-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);
+typedef struct {
+ const uint8_t* id;
+ size_t id_len;
+ UwMacaroonDelegateeType type;
+ uint32_t timestamp;
+} UwMacaroonDelegateeInfo;
+
+#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);
+
+/**
+ * Verify and validate the Macaroon, and put relevant information into the
+ * result object. Note that the resulting granted_scope will be the closest
+ * valid scope type (to the narrower side) defined in macaroon_caveat.h.
+ */
+bool uw_macaroon_validate_(
+ const UwMacaroon* macaroon,
+ const uint8_t* root_key,
+ size_t root_key_len,
+ const UwMacaroonContext* context,
+ UwMacaroonValidationResult* result);
-// 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);
+/** 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);
-// 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);
+/**
+ * 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..dc4ee3b 100644
--- a/third_party/libuweave/src/macaroon_caveat.c
+++ b/third_party/libuweave/src/macaroon_caveat.c
@@ -3,125 +3,298 @@
// 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
+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 kUwMacaroonCaveatTypeDelegateeService:
+ case kUwMacaroonCaveatTypeBleSessionID:
+ case kUwMacaroonCaveatTypeLanSessionID:
+ case kUwMacaroonCaveatTypeClientAuthorizationTokenV1:
+ case kUwMacaroonCaveatTypeServerAuthenticationTokenV1:
+ return true;
+ }
+ return false;
+}
-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
- return false;
+static bool is_valid_scope_type_(UwMacaroonCaveatScopeType type) {
+ switch (type) {
+ case kUwMacaroonCaveatScopeTypeOwner:
+ case kUwMacaroonCaveatScopeTypeManager:
+ case kUwMacaroonCaveatScopeTypeUser:
+ case kUwMacaroonCaveatScopeTypeViewer:
+ return true;
}
+ return false;
+}
- caveat->bytes = buffer;
- size_t encoded_str_len, total_str_len;
+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;
+ }
- 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;
+ total_str_len += encoded_str_len;
- 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;
+ new_caveat->bytes = buffer;
+ new_caveat->num_bytes = total_str_len;
+ return true;
+}
- default:
- // Should never reach here
- return false;
+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;
- 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,
- uint8_t* buffer,
- size_t buffer_size,
- UwMacaroonCaveat* caveat) {
- if (buffer == NULL || buffer_size == 0 || caveat == NULL) {
+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;
}
- if (type != kUwMacaroonCaveatTypeStop &&
- type != kUwMacaroonCaveatTypeSessionIdentifier) {
+
+ 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;
- return create_caveat_(type, NULL, 0, buffer, buffer_size, caveat);
+ new_caveat->bytes = buffer;
+ new_caveat->num_bytes = total_str_len;
+ return true;
}
-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;
+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 kUwMacaroonCaveatTypeDelegateeService:
+ case kUwMacaroonCaveatTypeLanSessionID:
+ case kUwMacaroonCaveatTypeClientAuthorizationTokenV1:
+ case kUwMacaroonCaveatTypeServerAuthenticationTokenV1:
+ return str_len + UW_MACAROON_ENCODING_MAX_UINT_CBOR_LEN;
+
+ default:
+ return 0; // For errors
}
+}
- return create_caveat_(type, &value, sizeof(uint32_t), buffer, buffer_size,
- caveat);
+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_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)) {
+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;
}
- if (type != kUwMacaroonCaveatTypeIdentifier) {
- 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* new_caveat) {
+ return create_caveat_bstr_value_(kUwMacaroonCaveatTypeDelegateeApp, id_str,
+ id_str_len, buffer, buffer_size, new_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_delegatee_service_(
+ 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_(kUwMacaroonCaveatTypeDelegateeService,
+ id_str, id_str_len, buffer, buffer_size,
+ new_caveat);
+}
+
+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);
+}
+
+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);
+}
- return create_caveat_(type, str, str_len, buffer, buffer_size, 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 +310,226 @@ bool uw_macaroon_caveat_get_type_(const UwMacaroonCaveat* caveat,
}
*type = (UwMacaroonCaveatType)unsigned_int;
+ return is_valid_caveat_type_(*type);
+}
+
+/* === 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;
+ }
- if (*type != kUwMacaroonCaveatTypeStop &&
- *type != kUwMacaroonCaveatTypeScope &&
- *type != kUwMacaroonCaveatTypeIdentifier &&
- *type != kUwMacaroonCaveatTypeIssued &&
- *type != kUwMacaroonCaveatTypeTTL &&
- *type != kUwMacaroonCaveatTypeExpiration &&
- *type != kUwMacaroonCaveatTypeSessionIdentifier) {
+ // 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,
+ uint32_t issued_time,
+ UwMacaroonValidationResult* result) {
+ if (result->num_delegatees >= MAX_NUM_DELEGATEES || issued_time == 0) {
+ return false;
+ }
+
+ UwMacaroonDelegateeType delegatee_type = kUwMacaroonDelegateeTypeNone;
+ switch (caveat_type) {
+ case kUwMacaroonCaveatTypeDelegateeUser:
+ delegatee_type = kUwMacaroonDelegateeTypeUser;
+ break;
+
+ case kUwMacaroonCaveatTypeDelegateeApp:
+ delegatee_type = kUwMacaroonDelegateeTypeApp;
+ break;
+
+ case kUwMacaroonCaveatTypeDelegateeService:
+ delegatee_type = kUwMacaroonDelegateeTypeService;
+ break;
+
+ default:
+ return false;
+ }
+
+ if (caveat_type != kUwMacaroonCaveatTypeDelegateeUser) {
+ for (size_t i = 0; i < result->num_delegatees; i++) {
+ // There must have at most one DelegateeApp or DelegateeService
+ if (result->delegatees[i].type == delegatee_type) {
+ 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].type = delegatee_type;
+ result->delegatees[result->num_delegatees].timestamp = issued_time;
+ 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:
+ if (!uw_macaroon_caveat_get_value_uint_(caveat, &issued_time) ||
+ issued_time < state->issued_time) {
+ return false;
+ }
+ state->issued_time = issued_time;
+ return true;
+
+ case kUwMacaroonCaveatTypeTTL1Hour:
+ if (state->issued_time == 0) {
+ return false;
+ }
+ return update_and_check_expiration_time(
+ context->current_time, state->issued_time + 60 * 60, result);
+
+ case kUwMacaroonCaveatTypeTTL24Hour:
+ if (state->issued_time == 0) {
+ 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:
+ case kUwMacaroonCaveatTypeDelegateeApp:
+ case kUwMacaroonCaveatTypeDelegateeService:
+ return update_delegatee_list(caveat_type, caveat, state->issued_time,
+ 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_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 +541,13 @@ bool uw_macaroon_caveat_get_value_uint_(const UwMacaroonCaveat* caveat,
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 +558,9 @@ bool uw_macaroon_caveat_get_value_uint_(const UwMacaroonCaveat* caveat,
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 +569,13 @@ bool uw_macaroon_caveat_get_value_str_(const UwMacaroonCaveat* caveat,
if (!uw_macaroon_caveat_get_type_(caveat, &type)) {
return false;
}
- if (type != kUwMacaroonCaveatTypeIdentifier) {
+ if (type != kUwMacaroonCaveatTypeNonce &&
+ type != kUwMacaroonCaveatTypeDelegateeUser &&
+ type != kUwMacaroonCaveatTypeDelegateeApp &&
+ type != kUwMacaroonCaveatTypeDelegateeService &&
+ type != kUwMacaroonCaveatTypeLanSessionID &&
+ type != kUwMacaroonCaveatTypeClientAuthorizationTokenV1 &&
+ type != kUwMacaroonCaveatTypeServerAuthenticationTokenV1) {
// Wrong type
return false;
}
@@ -200,48 +586,16 @@ bool uw_macaroon_caveat_get_value_str_(const UwMacaroonCaveat* caveat,
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) {
- 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)) {
+bool uw_macaroon_caveat_init_validation_state_(
+ UwMacaroonValidationState* state) {
+ if (state == NULL) {
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->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..4905667 100644
--- a/third_party/libuweave/src/macaroon_caveat.h
+++ b/third_party/libuweave/src/macaroon_caveat.h
@@ -15,13 +15,22 @@ typedef struct {
} 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
+ kUwMacaroonCaveatTypeDelegateeService = 12, // bstr
+
+ kUwMacaroonCaveatTypeAppCommandsOnly = 11, // no value
+ kUwMacaroonCaveatTypeBleSessionID = 16, // no value
+ kUwMacaroonCaveatTypeLanSessionID = 17, // bstr
+ kUwMacaroonCaveatTypeClientAuthorizationTokenV1 = 8193, // bstr (0x2001)
+ kUwMacaroonCaveatTypeServerAuthenticationTokenV1 = 12289, // bstr (0x3001)
} UwMacaroonCaveatType;
typedef enum {
@@ -31,28 +40,83 @@ typedef enum {
kUwMacaroonCaveatScopeTypeViewer = 20,
} UwMacaroonCaveatScopeType;
-bool uw_macaroon_caveat_create_without_value_(UwMacaroonCaveatType type,
+// For security sanity checks
+#define UW_MACAROON_CAVEAT_SCOPE_LOWEST_POSSIBLE 127
+
+/** 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_delegatee_service_(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_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..d6e7b07
--- /dev/null
+++ b/third_party/libuweave/src/macaroon_caveat_internal.h
@@ -0,0 +1,40 @@
+// 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 {
+ uint32_t issued_time; // 0 when invalid or not set.
+} 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 @@ typedef enum {
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_get_item_len_(const uint8_t* cbor, size_t cbor_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) {
if (buffer == NULL || buffer_size == 0 || resulting_cbor_len == NULL) {
return false;
@@ -88,7 +95,8 @@ bool uw_macaroon_encoding_encode_uint_(const uint32_t unsigned_int,
}
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 @@ bool uw_macaroon_encoding_encode_array_len_(const uint32_t array_len,
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 @@ bool uw_macaroon_encoding_encode_byte_str_(const uint8_t* str, size_t str_len,
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 @@ bool uw_macaroon_encoding_encode_text_str_(const uint8_t* str, size_t str_len,
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 @@ bool uw_macaroon_encoding_decode_array_len_(const uint8_t* cbor,
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 @@ bool uw_macaroon_encoding_decode_byte_str_(const uint8_t* cbor, size_t cbor_len,
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 @@ static inline size_t uint_min_len_(uint32_t unsigned_int) {
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 @@ static inline bool write_uint_big_endian_(uint32_t unsigned_int, uint8_t* buff,
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 @@ static inline bool read_uint_big_endian_(const uint8_t* bytes, size_t num_bytes,
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 @@ static bool blindly_encode_uint_(uint32_t unsigned_int, uint8_t* buffer,
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 @@ static bool blindly_encode_str_(const uint8_t* str, size_t str_len,
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 @@ static bool blindly_decode_uint_(const uint8_t* cbor, size_t cbor_len,
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);