diff options
Diffstat (limited to 'third_party')
-rwxr-xr-x | third_party/get_libevhtp.sh | 8 | ||||
-rw-r--r-- | third_party/libuweave/src/crypto_hmac.c | 51 | ||||
-rw-r--r-- | third_party/libuweave/src/crypto_hmac.h | 30 | ||||
-rw-r--r-- | third_party/libuweave/src/crypto_utils.c | 7 | ||||
-rw-r--r-- | third_party/libuweave/src/macaroon.c | 289 | ||||
-rw-r--r-- | third_party/libuweave/src/macaroon.h | 98 | ||||
-rw-r--r-- | third_party/libuweave/src/macaroon_caveat.c | 620 | ||||
-rw-r--r-- | third_party/libuweave/src/macaroon_caveat.h | 112 | ||||
-rw-r--r-- | third_party/libuweave/src/macaroon_caveat_internal.h | 40 | ||||
-rw-r--r-- | third_party/libuweave/src/macaroon_context.c | 24 | ||||
-rw-r--r-- | third_party/libuweave/src/macaroon_context.h | 18 | ||||
-rw-r--r-- | third_party/libuweave/src/macaroon_encoding.c | 103 | ||||
-rw-r--r-- | third_party/libuweave/src/macaroon_encoding.h | 47 |
13 files changed, 1043 insertions, 404 deletions
diff --git a/third_party/get_libevhtp.sh b/third_party/get_libevhtp.sh index c270813..cfcada9 100755 --- a/third_party/get_libevhtp.sh +++ b/third_party/get_libevhtp.sh @@ -9,17 +9,19 @@ cd $(dirname "$0") THIRD_PARTY=$(pwd) +LIBEVHTP_VERSION=1.2.11n + mkdir -p include lib rm -rf $THIRD_PARTY/libevhtp -curl -L https://github.com/ellzey/libevhtp/archive/1.2.10.tar.gz | tar xz || exit 1 -mv libevhtp-1.2.10 $THIRD_PARTY/libevhtp || exit 1 +curl -L https://github.com/ellzey/libevhtp/archive/$LIBEVHTP_VERSION.tar.gz | tar xz || exit 1 +mv libevhtp-$LIBEVHTP_VERSION $THIRD_PARTY/libevhtp || exit 1 cd $THIRD_PARTY/libevhtp || exit 1 cmake -D EVHTP_DISABLE_REGEX:BOOL=ON . || exit 1 make evhtp || exit 1 -cp -rf evhtp-config.h evhtp.h evthr/evthr.h htparse/htparse.h $THIRD_PARTY/include/ || exit 1 +cp -rf *.h $THIRD_PARTY/include/ || exit 1 cp -f libevhtp.a $THIRD_PARTY/lib/ || exit 1 rm -rf $THIRD_PARTY/libevhtp 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); |