From 7d29a5a5402badd1c24a8542539306a521c14cc1 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Wed, 27 Jan 2016 14:21:37 -0800 Subject: Update macaroon lib Change-Id: I71f2aacbc094b3e4cbd10898d037719ac59c4015 Reviewed-on: https://weave-review.googlesource.com/2359 Reviewed-by: Vitaly Buka --- third_party/libuweave/src/crypto_hmac.h | 30 +- third_party/libuweave/src/crypto_utils.c | 7 - third_party/libuweave/src/macaroon.c | 286 ++++++---- third_party/libuweave/src/macaroon.h | 89 ++-- third_party/libuweave/src/macaroon_caveat.c | 591 ++++++++++++++++----- third_party/libuweave/src/macaroon_caveat.h | 105 +++- .../libuweave/src/macaroon_caveat_internal.h | 41 ++ third_party/libuweave/src/macaroon_context.c | 24 +- third_party/libuweave/src/macaroon_context.h | 18 +- third_party/libuweave/src/macaroon_encoding.c | 103 ++-- third_party/libuweave/src/macaroon_encoding.h | 47 +- 11 files changed, 974 insertions(+), 367 deletions(-) create mode 100644 third_party/libuweave/src/macaroon_caveat_internal.h (limited to 'third_party/libuweave/src') 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 #include -// 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 @@ 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,228 @@ 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->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); - 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; + } + } + + 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..dfaaba7 100644 --- a/third_party/libuweave/src/macaroon.h +++ b/third_party/libuweave/src/macaroon.h @@ -9,7 +9,8 @@ #include #include -#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; + +#define MAX_NUM_DELEGATEES 10 -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 { + 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; -bool uw_macaroon_verify_(const UwMacaroon* macaroon, - const uint8_t* root_key, - size_t root_key_len); +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); -// Create a new macaroon with a new caveat +/** 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. + */ +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..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 #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 - return false; +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; +} - caveat->bytes = buffer; - size_t encoded_str_len, total_str_len; +static bool is_valid_scope_type_(UwMacaroonCaveatScopeType type) { + switch (type) { + case kUwMacaroonCaveatScopeTypeOwner: + case kUwMacaroonCaveatScopeTypeManager: + case kUwMacaroonCaveatScopeTypeUser: + case kUwMacaroonCaveatScopeTypeViewer: + return true; + } + return false; +} - uint32_t unsigned_int = (uint32_t)type; - if (!uw_macaroon_encoding_encode_uint_(unsigned_int, buffer, buffer_size, - &encoded_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; } - 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; + 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; - 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_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; } - 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_uint_(unsigned_int, 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) { +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 != kUwMacaroonCaveatTypeScope && - type != kUwMacaroonCaveatTypeIssued && - type != kUwMacaroonCaveatTypeTTL && - type != kUwMacaroonCaveatTypeExpiration) { + + 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, &value, sizeof(uint32_t), buffer, buffer_size, - caveat); + new_caveat->bytes = buffer; + new_caveat->num_bytes = total_str_len; + return true; } -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; +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 } - if (type != kUwMacaroonCaveatTypeIdentifier) { +} + +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_(type, str, str_len, buffer, buffer_size, caveat); + 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_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); +} + +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 @@ 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 === */ - if (*type != kUwMacaroonCaveatTypeStop && - *type != kUwMacaroonCaveatTypeScope && - *type != kUwMacaroonCaveatTypeIdentifier && - *type != kUwMacaroonCaveatTypeIssued && - *type != kUwMacaroonCaveatTypeTTL && - *type != kUwMacaroonCaveatTypeExpiration && - *type != kUwMacaroonCaveatTypeSessionIdentifier) { +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 @@ 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 +529,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 +540,12 @@ 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 != kUwMacaroonCaveatTypeLanSessionID && + type != kUwMacaroonCaveatTypeClientAuthorizationTokenV1 && + type != kUwMacaroonCaveatTypeServerAuthenticationTokenV1) { // Wrong type return false; } @@ -200,48 +556,17 @@ 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_()) { +bool uw_macaroon_caveat_init_validation_state_( + UwMacaroonValidationState* state) { + if (state == NULL) { 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 @@ 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 + 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 @@ typedef enum { 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 +#include +#include + +#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 #include @@ -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 #include -// 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); -- cgit v1.2.3 From a821f2ec61873d1ad9eb207d7b760b3aaf21248e Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Wed, 27 Jan 2016 11:44:02 -0800 Subject: Integrate new macaroon library Implement validation of auth tokens (no session id check yet). BUG: 26292014 Change-Id: I55c9c8249f6355132486b2be8628c3538d504c5d Reviewed-on: https://weave-review.googlesource.com/2375 Reviewed-by: Alex Vakulenko --- third_party/libuweave/src/crypto_hmac.c | 51 +++++++++++---------------------- 1 file changed, 17 insertions(+), 34 deletions(-) (limited to 'third_party/libuweave/src') 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 #include -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); } -- cgit v1.2.3 From d74a732bfae910b08d6d0f83a86cde04c3aa2cd5 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Wed, 27 Jan 2016 18:39:36 -0800 Subject: Update macaroon lib Change-Id: I37472f11827b8bf1af28c6f525df85093f5f3a56 Reviewed-on: https://weave-review.googlesource.com/2381 Reviewed-by: Alex Vakulenko --- third_party/libuweave/src/macaroon.c | 2 +- third_party/libuweave/src/macaroon.h | 9 +++++- third_party/libuweave/src/macaroon_caveat.c | 48 +++++++++++++++++++++++------ third_party/libuweave/src/macaroon_caveat.h | 24 ++++++++++----- 4 files changed, 63 insertions(+), 20 deletions(-) (limited to 'third_party/libuweave/src') diff --git a/third_party/libuweave/src/macaroon.c b/third_party/libuweave/src/macaroon.c index 50b2d00..aa775c2 100644 --- a/third_party/libuweave/src/macaroon.c +++ b/third_party/libuweave/src/macaroon.c @@ -146,7 +146,7 @@ static void reset_validation_result(UwMacaroonValidationResult* result) { 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; + result->delegatees[i].type = kUwMacaroonDelegateeTypeNone; } } diff --git a/third_party/libuweave/src/macaroon.h b/third_party/libuweave/src/macaroon.h index dfaaba7..c93bbb2 100644 --- a/third_party/libuweave/src/macaroon.h +++ b/third_party/libuweave/src/macaroon.h @@ -25,10 +25,17 @@ typedef struct { } UwMacaroon; // For the delegatee list in the validation result object +typedef enum { + kUwMacaroonDelegateeTypeNone = 0, + kUwMacaroonDelegateeTypeUser = 1, + kUwMacaroonDelegateeTypeApp = 2, + kUwMacaroonDelegateeTypeService = 3, +} UwMacaroonDelegateeType; + typedef struct { const uint8_t* id; size_t id_len; - bool is_app; + UwMacaroonDelegateeType type; } UwMacaroonDelegateeInfo; #define MAX_NUM_DELEGATEES 10 diff --git a/third_party/libuweave/src/macaroon_caveat.c b/third_party/libuweave/src/macaroon_caveat.c index b8b2183..a2b26dc 100644 --- a/third_party/libuweave/src/macaroon_caveat.c +++ b/third_party/libuweave/src/macaroon_caveat.c @@ -12,8 +12,6 @@ #include "src/macaroon_context.h" #include "src/macaroon_encoding.h" -#define MAX_CBOR_STR_LEN_FOR_UINT 5 - static bool is_valid_caveat_type_(UwMacaroonCaveatType type) { switch (type) { case kUwMacaroonCaveatTypeNonce: @@ -25,6 +23,7 @@ static bool is_valid_caveat_type_(UwMacaroonCaveatType type) { case kUwMacaroonCaveatTypeDelegateeUser: case kUwMacaroonCaveatTypeDelegateeApp: case kUwMacaroonCaveatTypeAppCommandsOnly: + case kUwMacaroonCaveatTypeDelegateeService: case kUwMacaroonCaveatTypeBleSessionID: case kUwMacaroonCaveatTypeLanSessionID: case kUwMacaroonCaveatTypeClientAuthorizationTokenV1: @@ -103,7 +102,7 @@ static bool create_caveat_bstr_value_(UwMacaroonCaveatType type, uint8_t* buffer, size_t buffer_size, UwMacaroonCaveat* new_caveat) { - if ((str == NULL && str_len != 0) || buffer == NULL || buffer_size == 0 || + 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; @@ -147,6 +146,7 @@ size_t uw_macaroon_caveat_creation_get_buffsize_(UwMacaroonCaveatType type, case kUwMacaroonCaveatTypeNonce: case kUwMacaroonCaveatTypeDelegateeUser: case kUwMacaroonCaveatTypeDelegateeApp: + case kUwMacaroonCaveatTypeDelegateeService: case kUwMacaroonCaveatTypeLanSessionID: case kUwMacaroonCaveatTypeClientAuthorizationTokenV1: case kUwMacaroonCaveatTypeServerAuthenticationTokenV1: @@ -237,6 +237,17 @@ bool uw_macaroon_caveat_create_app_commands_only_( 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) { @@ -393,12 +404,29 @@ static bool update_delegatee_list(UwMacaroonCaveatType caveat_type, if (result->num_delegatees >= MAX_NUM_DELEGATEES) { return false; } - bool is_app = (caveat_type == kUwMacaroonCaveatTypeDelegateeApp); - if (is_app) { + 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 - if (result->delegatees[i].is_app) { + // There must have at most one DelegateeApp or DelegateeService + if (result->delegatees[i].type == delegatee_type) { return false; } } @@ -409,7 +437,7 @@ static bool update_delegatee_list(UwMacaroonCaveatType caveat_type, &(result->delegatees[result->num_delegatees].id_len))) { return false; } - result->delegatees[result->num_delegatees].is_app = is_app; + result->delegatees[result->num_delegatees].type = delegatee_type; result->num_delegatees++; return true; } @@ -463,9 +491,8 @@ bool uw_macaroon_caveat_validate_(const UwMacaroonCaveat* caveat, // Need to create a list of delegatees case kUwMacaroonCaveatTypeDelegateeUser: - return update_delegatee_list(caveat_type, caveat, result); - case kUwMacaroonCaveatTypeDelegateeApp: + case kUwMacaroonCaveatTypeDelegateeService: return update_delegatee_list(caveat_type, caveat, result); // Time related caveats @@ -543,6 +570,7 @@ bool uw_macaroon_caveat_get_value_bstr_(const UwMacaroonCaveat* caveat, if (type != kUwMacaroonCaveatTypeNonce && type != kUwMacaroonCaveatTypeDelegateeUser && type != kUwMacaroonCaveatTypeDelegateeApp && + type != kUwMacaroonCaveatTypeDelegateeService && type != kUwMacaroonCaveatTypeLanSessionID && type != kUwMacaroonCaveatTypeClientAuthorizationTokenV1 && type != kUwMacaroonCaveatTypeServerAuthenticationTokenV1) { diff --git a/third_party/libuweave/src/macaroon_caveat.h b/third_party/libuweave/src/macaroon_caveat.h index 9baf70d..b6846e8 100644 --- a/third_party/libuweave/src/macaroon_caveat.h +++ b/third_party/libuweave/src/macaroon_caveat.h @@ -15,14 +15,17 @@ typedef struct { } UwMacaroonCaveat; typedef enum { - 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 + 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 @@ -81,6 +84,11 @@ bool uw_macaroon_caveat_create_delegatee_app_(const uint8_t* id_str, 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); -- cgit v1.2.3 From 3cbb6869edd05975fc876844bfff52d12ac32f66 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Thu, 28 Jan 2016 16:01:13 -0800 Subject: Update macaroon lib with version supporting empty strings Use "" for delegation to the device owner. Change-Id: Ibb4a1da07817eebcbe8b0675381f98af3fdbe947 Reviewed-on: https://weave-review.googlesource.com/2391 Reviewed-by: Vitaly Buka --- third_party/libuweave/src/macaroon_caveat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'third_party/libuweave/src') diff --git a/third_party/libuweave/src/macaroon_caveat.c b/third_party/libuweave/src/macaroon_caveat.c index a2b26dc..3b26b29 100644 --- a/third_party/libuweave/src/macaroon_caveat.c +++ b/third_party/libuweave/src/macaroon_caveat.c @@ -102,7 +102,7 @@ static bool create_caveat_bstr_value_(UwMacaroonCaveatType type, uint8_t* buffer, size_t buffer_size, UwMacaroonCaveat* new_caveat) { - if (str == NULL || str_len == 0 || buffer == NULL || buffer_size == 0 || + 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; -- cgit v1.2.3 From 4efdf4637d19d6fd6c1725820fd07a5702e71a56 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Fri, 29 Jan 2016 14:21:39 -0800 Subject: Fix GCC warning Change-Id: I7ad142d9873d71e6791dfbbb1ebdff7a6b0f5371 Reviewed-on: https://weave-review.googlesource.com/2396 Reviewed-by: Vitaly Buka --- third_party/libuweave/src/macaroon.c | 3 +-- third_party/libuweave/src/macaroon_caveat.c | 4 +++- third_party/libuweave/src/macaroon_caveat.h | 4 ---- 3 files changed, 4 insertions(+), 7 deletions(-) (limited to 'third_party/libuweave/src') diff --git a/third_party/libuweave/src/macaroon.c b/third_party/libuweave/src/macaroon.c index aa775c2..80e5933 100644 --- a/third_party/libuweave/src/macaroon.c +++ b/third_party/libuweave/src/macaroon.c @@ -135,8 +135,7 @@ static void init_validation_result(UwMacaroonValidationResult* result) { /** 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->granted_scope = 0; result->expiration_time = 0; result->weave_app_restricted = true; result->lan_session_id = NULL; diff --git a/third_party/libuweave/src/macaroon_caveat.c b/third_party/libuweave/src/macaroon_caveat.c index 3b26b29..85d8bbb 100644 --- a/third_party/libuweave/src/macaroon_caveat.c +++ b/third_party/libuweave/src/macaroon_caveat.c @@ -12,6 +12,9 @@ #include "src/macaroon_context.h" #include "src/macaroon_encoding.h" +// For security sanity checks +#define UW_MACAROON_CAVEAT_SCOPE_LOWEST_POSSIBLE 127 + static bool is_valid_caveat_type_(UwMacaroonCaveatType type) { switch (type) { case kUwMacaroonCaveatTypeNonce: @@ -507,7 +510,6 @@ bool uw_macaroon_caveat_validate_(const UwMacaroonCaveat* caveat, 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; } diff --git a/third_party/libuweave/src/macaroon_caveat.h b/third_party/libuweave/src/macaroon_caveat.h index b6846e8..33f9d24 100644 --- a/third_party/libuweave/src/macaroon_caveat.h +++ b/third_party/libuweave/src/macaroon_caveat.h @@ -33,10 +33,6 @@ typedef enum { 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, -- cgit v1.2.3 From 08be74de678930e6823f9fe7e460c35bb58040f9 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Tue, 2 Feb 2016 15:25:09 -0800 Subject: Update libuweave/macaroon code Added delegation time stamp into access token to match changed validation logic of macaroons. BUG: 26728665 Change-Id: I131b92b0e0b1b2274d80bdc0b5790a8c05071ec5 Reviewed-on: https://weave-review.googlesource.com/2467 Reviewed-by: Vitaly Buka --- third_party/libuweave/src/macaroon.c | 40 ++++++++++++---------- third_party/libuweave/src/macaroon.h | 4 ++- third_party/libuweave/src/macaroon_caveat.c | 19 +++++----- third_party/libuweave/src/macaroon_caveat.h | 3 ++ .../libuweave/src/macaroon_caveat_internal.h | 3 +- 5 files changed, 38 insertions(+), 31 deletions(-) (limited to 'third_party/libuweave/src') diff --git a/third_party/libuweave/src/macaroon.c b/third_party/libuweave/src/macaroon.c index 80e5933..c823804 100644 --- a/third_party/libuweave/src/macaroon.c +++ b/third_party/libuweave/src/macaroon.c @@ -124,29 +124,32 @@ bool uw_macaroon_extend_(const UwMacaroon* old_macaroon, 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; + *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) { - // Start from the largest scope or highest privilege - result->granted_scope = 0; - 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].type = kUwMacaroonDelegateeTypeNone; + *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, @@ -178,6 +181,7 @@ bool uw_macaroon_validate_(const UwMacaroon* macaroon, } } + result->granted_scope = get_closest_scope(result->granted_scope); return true; } diff --git a/third_party/libuweave/src/macaroon.h b/third_party/libuweave/src/macaroon.h index c93bbb2..c739bca 100644 --- a/third_party/libuweave/src/macaroon.h +++ b/third_party/libuweave/src/macaroon.h @@ -36,6 +36,7 @@ typedef struct { const uint8_t* id; size_t id_len; UwMacaroonDelegateeType type; + uint32_t timestamp; } UwMacaroonDelegateeInfo; #define MAX_NUM_DELEGATEES 10 @@ -67,7 +68,8 @@ bool uw_macaroon_extend_(const UwMacaroon* old_macaroon, /** * Verify and validate the Macaroon, and put relevant information into the - * result object. + * 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, diff --git a/third_party/libuweave/src/macaroon_caveat.c b/third_party/libuweave/src/macaroon_caveat.c index 85d8bbb..dc4ee3b 100644 --- a/third_party/libuweave/src/macaroon_caveat.c +++ b/third_party/libuweave/src/macaroon_caveat.c @@ -12,9 +12,6 @@ #include "src/macaroon_context.h" #include "src/macaroon_encoding.h" -// For security sanity checks -#define UW_MACAROON_CAVEAT_SCOPE_LOWEST_POSSIBLE 127 - static bool is_valid_caveat_type_(UwMacaroonCaveatType type) { switch (type) { case kUwMacaroonCaveatTypeNonce: @@ -403,8 +400,9 @@ static bool update_and_check_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) { + if (result->num_delegatees >= MAX_NUM_DELEGATEES || issued_time == 0) { return false; } @@ -441,6 +439,7 @@ static bool update_delegatee_list(UwMacaroonCaveatType caveat_type, return false; } result->delegatees[result->num_delegatees].type = delegatee_type; + result->delegatees[result->num_delegatees].timestamp = issued_time; result->num_delegatees++; return true; } @@ -471,22 +470,22 @@ bool uw_macaroon_caveat_validate_(const UwMacaroonCaveat* caveat, return true; case kUwMacaroonCaveatTypeDelegationTimestamp: - state->has_issued_time = true; - if (!uw_macaroon_caveat_get_value_uint_(caveat, &issued_time)) { + 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->has_issued_time)) { + 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->has_issued_time)) { + if (state->issued_time == 0) { return false; } return update_and_check_expiration_time( @@ -496,7 +495,8 @@ bool uw_macaroon_caveat_validate_(const UwMacaroonCaveat* caveat, case kUwMacaroonCaveatTypeDelegateeUser: case kUwMacaroonCaveatTypeDelegateeApp: case kUwMacaroonCaveatTypeDelegateeService: - return update_delegatee_list(caveat_type, caveat, result); + return update_delegatee_list(caveat_type, caveat, state->issued_time, + result); // Time related caveats case kUwMacaroonCaveatTypeExpirationAbsolute: @@ -596,7 +596,6 @@ bool uw_macaroon_caveat_init_validation_state_( return false; } - 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 33f9d24..4905667 100644 --- a/third_party/libuweave/src/macaroon_caveat.h +++ b/third_party/libuweave/src/macaroon_caveat.h @@ -40,6 +40,9 @@ typedef enum { kUwMacaroonCaveatScopeTypeViewer = 20, } UwMacaroonCaveatScopeType; +// 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); diff --git a/third_party/libuweave/src/macaroon_caveat_internal.h b/third_party/libuweave/src/macaroon_caveat_internal.h index 46a72fb..d6e7b07 100644 --- a/third_party/libuweave/src/macaroon_caveat_internal.h +++ b/third_party/libuweave/src/macaroon_caveat_internal.h @@ -20,8 +20,7 @@ bool uw_macaroon_caveat_sign_(const uint8_t* key, size_t mac_tag_size); typedef struct { - bool has_issued_time; - uint32_t issued_time; + uint32_t issued_time; // 0 when invalid or not set. } UwMacaroonValidationState; bool uw_macaroon_caveat_init_validation_state_( -- cgit v1.2.3