Home | History | Annotate | Download | only in src
      1 // Copyright 2015 The Weave Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "src/macaroon_caveat.h"
      6 #include "src/macaroon_caveat_internal.h"
      7 
      8 #include <string.h>
      9 
     10 #include "src/crypto_hmac.h"
     11 #include "src/macaroon.h"
     12 #include "src/macaroon_context.h"
     13 #include "src/macaroon_encoding.h"
     14 
     15 static bool is_valid_caveat_type_(UwMacaroonCaveatType type) {
     16   switch (type) {
     17     case kUwMacaroonCaveatTypeNonce:
     18     case kUwMacaroonCaveatTypeScope:
     19     case kUwMacaroonCaveatTypeExpirationAbsolute:
     20     case kUwMacaroonCaveatTypeTTL1Hour:
     21     case kUwMacaroonCaveatTypeTTL24Hour:
     22     case kUwMacaroonCaveatTypeDelegationTimestamp:
     23     case kUwMacaroonCaveatTypeDelegateeUser:
     24     case kUwMacaroonCaveatTypeDelegateeApp:
     25     case kUwMacaroonCaveatTypeAppCommandsOnly:
     26     case kUwMacaroonCaveatTypeDelegateeService:
     27     case kUwMacaroonCaveatTypeBleSessionID:
     28     case kUwMacaroonCaveatTypeLanSessionID:
     29     case kUwMacaroonCaveatTypeClientAuthorizationTokenV1:
     30     case kUwMacaroonCaveatTypeServerAuthenticationTokenV1:
     31       return true;
     32   }
     33   return false;
     34 }
     35 
     36 static bool is_valid_scope_type_(UwMacaroonCaveatScopeType type) {
     37   switch (type) {
     38     case kUwMacaroonCaveatScopeTypeOwner:
     39     case kUwMacaroonCaveatScopeTypeManager:
     40     case kUwMacaroonCaveatScopeTypeUser:
     41     case kUwMacaroonCaveatScopeTypeViewer:
     42       return true;
     43   }
     44   return false;
     45 }
     46 
     47 static bool create_caveat_no_value_(UwMacaroonCaveatType type,
     48                                     uint8_t* buffer,
     49                                     size_t buffer_size,
     50                                     UwMacaroonCaveat* new_caveat) {
     51   // (buffer_size == 0 || get_buffer_size_() > buffer_size) will conver the case
     52   // that get_buffer_size_() returns 0 (for errors), so there is no need to
     53   // check get_buffer_size_() == 0 again.
     54   if (buffer == NULL || buffer_size == 0 || new_caveat == NULL ||
     55       uw_macaroon_caveat_creation_get_buffsize_(type, 0) > buffer_size) {
     56     return false;
     57   }
     58 
     59   size_t encoded_str_len = 0, total_str_len = 0;
     60   if (!uw_macaroon_encoding_encode_uint_((uint32_t)type, buffer, buffer_size,
     61                                          &encoded_str_len)) {
     62     return false;
     63   }
     64   total_str_len += encoded_str_len;
     65 
     66   new_caveat->bytes = buffer;
     67   new_caveat->num_bytes = total_str_len;
     68   return true;
     69 }
     70 
     71 static bool create_caveat_uint_value_(UwMacaroonCaveatType type,
     72                                       uint32_t unsigned_int,
     73                                       uint8_t* buffer,
     74                                       size_t buffer_size,
     75                                       UwMacaroonCaveat* new_caveat) {
     76   if (buffer == NULL || buffer_size == 0 || new_caveat == NULL ||
     77       uw_macaroon_caveat_creation_get_buffsize_(type, 0) > buffer_size) {
     78     return false;
     79   }
     80 
     81   size_t encoded_str_len = 0, total_str_len = 0;
     82   if (!uw_macaroon_encoding_encode_uint_((uint32_t)type, buffer, buffer_size,
     83                                          &encoded_str_len)) {
     84     return false;
     85   }
     86   total_str_len += encoded_str_len;
     87   if (!uw_macaroon_encoding_encode_uint_(unsigned_int, buffer + total_str_len,
     88                                          buffer_size - total_str_len,
     89                                          &encoded_str_len)) {
     90     return false;
     91   }
     92   total_str_len += encoded_str_len;
     93 
     94   new_caveat->bytes = buffer;
     95   new_caveat->num_bytes = total_str_len;
     96   return true;
     97 }
     98 
     99 static bool create_caveat_bstr_value_(UwMacaroonCaveatType type,
    100                                       const uint8_t* str,
    101                                       size_t str_len,
    102                                       uint8_t* buffer,
    103                                       size_t buffer_size,
    104                                       UwMacaroonCaveat* new_caveat) {
    105   if ((str == NULL && str_len != 0) || buffer == NULL || buffer_size == 0 ||
    106       new_caveat == NULL ||
    107       uw_macaroon_caveat_creation_get_buffsize_(type, str_len) > buffer_size) {
    108     return false;
    109   }
    110 
    111   size_t encoded_str_len = 0, total_str_len = 0;
    112   if (!uw_macaroon_encoding_encode_uint_((uint32_t)type, buffer, buffer_size,
    113                                          &encoded_str_len)) {
    114     return false;
    115   }
    116   total_str_len += encoded_str_len;
    117   if (!uw_macaroon_encoding_encode_byte_str_(
    118           str, str_len, buffer + total_str_len, buffer_size - total_str_len,
    119           &encoded_str_len)) {
    120     return false;
    121   }
    122   total_str_len += encoded_str_len;
    123 
    124   new_caveat->bytes = buffer;
    125   new_caveat->num_bytes = total_str_len;
    126   return true;
    127 }
    128 
    129 size_t uw_macaroon_caveat_creation_get_buffsize_(UwMacaroonCaveatType type,
    130                                                  size_t str_len) {
    131   switch (type) {
    132     // No values
    133     case kUwMacaroonCaveatTypeTTL1Hour:
    134     case kUwMacaroonCaveatTypeTTL24Hour:
    135     case kUwMacaroonCaveatTypeAppCommandsOnly:
    136     case kUwMacaroonCaveatTypeBleSessionID:
    137       return UW_MACAROON_ENCODING_MAX_UINT_CBOR_LEN;
    138 
    139     // Unsigned integers
    140     case kUwMacaroonCaveatTypeScope:
    141     case kUwMacaroonCaveatTypeExpirationAbsolute:
    142     case kUwMacaroonCaveatTypeDelegationTimestamp:
    143       return 2 * UW_MACAROON_ENCODING_MAX_UINT_CBOR_LEN;
    144 
    145     // Byte strings
    146     case kUwMacaroonCaveatTypeNonce:
    147     case kUwMacaroonCaveatTypeDelegateeUser:
    148     case kUwMacaroonCaveatTypeDelegateeApp:
    149     case kUwMacaroonCaveatTypeDelegateeService:
    150     case kUwMacaroonCaveatTypeLanSessionID:
    151     case kUwMacaroonCaveatTypeClientAuthorizationTokenV1:
    152     case kUwMacaroonCaveatTypeServerAuthenticationTokenV1:
    153       return str_len + UW_MACAROON_ENCODING_MAX_UINT_CBOR_LEN;
    154 
    155     default:
    156       return 0;  // For errors
    157   }
    158 }
    159 
    160 bool uw_macaroon_caveat_create_nonce_(const uint8_t* nonce,
    161                                       size_t nonce_size,
    162                                       uint8_t* buffer,
    163                                       size_t buffer_size,
    164                                       UwMacaroonCaveat* new_caveat) {
    165   return create_caveat_bstr_value_(kUwMacaroonCaveatTypeNonce, nonce,
    166                                    nonce_size, buffer, buffer_size, new_caveat);
    167 }
    168 
    169 bool uw_macaroon_caveat_create_scope_(UwMacaroonCaveatScopeType scope,
    170                                       uint8_t* buffer,
    171                                       size_t buffer_size,
    172                                       UwMacaroonCaveat* new_caveat) {
    173   if (!is_valid_scope_type_(scope)) {
    174     return false;
    175   }
    176 
    177   return create_caveat_uint_value_(kUwMacaroonCaveatTypeScope, scope, buffer,
    178                                    buffer_size, new_caveat);
    179 }
    180 
    181 bool uw_macaroon_caveat_create_expiration_absolute_(
    182     uint32_t expiration_time,
    183     uint8_t* buffer,
    184     size_t buffer_size,
    185     UwMacaroonCaveat* new_caveat) {
    186   return create_caveat_uint_value_(kUwMacaroonCaveatTypeExpirationAbsolute,
    187                                    expiration_time, buffer, buffer_size,
    188                                    new_caveat);
    189 }
    190 
    191 bool uw_macaroon_caveat_create_ttl_1_hour_(uint8_t* buffer,
    192                                            size_t buffer_size,
    193                                            UwMacaroonCaveat* new_caveat) {
    194   return create_caveat_no_value_(kUwMacaroonCaveatTypeTTL1Hour, buffer,
    195                                  buffer_size, new_caveat);
    196 }
    197 
    198 bool uw_macaroon_caveat_create_ttl_24_hour_(uint8_t* buffer,
    199                                             size_t buffer_size,
    200                                             UwMacaroonCaveat* new_caveat) {
    201   return create_caveat_no_value_(kUwMacaroonCaveatTypeTTL24Hour, buffer,
    202                                  buffer_size, new_caveat);
    203 }
    204 
    205 bool uw_macaroon_caveat_create_delegation_timestamp_(
    206     uint32_t timestamp,
    207     uint8_t* buffer,
    208     size_t buffer_size,
    209     UwMacaroonCaveat* new_caveat) {
    210   return create_caveat_uint_value_(kUwMacaroonCaveatTypeDelegationTimestamp,
    211                                    timestamp, buffer, buffer_size, new_caveat);
    212 }
    213 
    214 bool uw_macaroon_caveat_create_delegatee_user_(const uint8_t* id_str,
    215                                                size_t id_str_len,
    216                                                uint8_t* buffer,
    217                                                size_t buffer_size,
    218                                                UwMacaroonCaveat* new_caveat) {
    219   return create_caveat_bstr_value_(kUwMacaroonCaveatTypeDelegateeUser, id_str,
    220                                    id_str_len, buffer, buffer_size, new_caveat);
    221 }
    222 
    223 bool uw_macaroon_caveat_create_delegatee_app_(const uint8_t* id_str,
    224                                               size_t id_str_len,
    225                                               uint8_t* buffer,
    226                                               size_t buffer_size,
    227                                               UwMacaroonCaveat* new_caveat) {
    228   return create_caveat_bstr_value_(kUwMacaroonCaveatTypeDelegateeApp, id_str,
    229                                    id_str_len, buffer, buffer_size, new_caveat);
    230 }
    231 
    232 bool uw_macaroon_caveat_create_app_commands_only_(
    233     uint8_t* buffer,
    234     size_t buffer_size,
    235     UwMacaroonCaveat* new_caveat) {
    236   return create_caveat_no_value_(kUwMacaroonCaveatTypeAppCommandsOnly, buffer,
    237                                  buffer_size, new_caveat);
    238 }
    239 
    240 bool uw_macaroon_caveat_create_delegatee_service_(
    241     const uint8_t* id_str,
    242     size_t id_str_len,
    243     uint8_t* buffer,
    244     size_t buffer_size,
    245     UwMacaroonCaveat* new_caveat) {
    246   return create_caveat_bstr_value_(kUwMacaroonCaveatTypeDelegateeService,
    247                                    id_str, id_str_len, buffer, buffer_size,
    248                                    new_caveat);
    249 }
    250 
    251 bool uw_macaroon_caveat_create_ble_session_id_(uint8_t* buffer,
    252                                                size_t buffer_size,
    253                                                UwMacaroonCaveat* new_caveat) {
    254   return create_caveat_no_value_(kUwMacaroonCaveatTypeBleSessionID, buffer,
    255                                  buffer_size, new_caveat);
    256 }
    257 
    258 bool uw_macaroon_caveat_create_lan_session_id_(const uint8_t* session_id,
    259                                                size_t session_id_len,
    260                                                uint8_t* buffer,
    261                                                size_t buffer_size,
    262                                                UwMacaroonCaveat* new_caveat) {
    263   return create_caveat_bstr_value_(kUwMacaroonCaveatTypeLanSessionID,
    264                                    session_id, session_id_len, buffer,
    265                                    buffer_size, new_caveat);
    266 }
    267 
    268 bool uw_macaroon_caveat_create_client_authorization_token_(
    269     const uint8_t* str,
    270     size_t str_len,
    271     uint8_t* buffer,
    272     size_t buffer_size,
    273     UwMacaroonCaveat* new_caveat) {
    274   if (str_len == 0) {
    275     return create_caveat_no_value_(
    276         kUwMacaroonCaveatTypeClientAuthorizationTokenV1, buffer, buffer_size,
    277         new_caveat);
    278   }
    279   return create_caveat_bstr_value_(
    280       kUwMacaroonCaveatTypeClientAuthorizationTokenV1, str, str_len, buffer,
    281       buffer_size, new_caveat);
    282 }
    283 
    284 bool uw_macaroon_caveat_create_server_authentication_token_(
    285     const uint8_t* str,
    286     size_t str_len,
    287     uint8_t* buffer,
    288     size_t buffer_size,
    289     UwMacaroonCaveat* new_caveat) {
    290   if (str_len == 0) {
    291     return create_caveat_no_value_(
    292         kUwMacaroonCaveatTypeServerAuthenticationTokenV1, buffer, buffer_size,
    293         new_caveat);
    294   }
    295   return create_caveat_bstr_value_(
    296       kUwMacaroonCaveatTypeServerAuthenticationTokenV1, str, str_len, buffer,
    297       buffer_size, new_caveat);
    298 }
    299 
    300 bool uw_macaroon_caveat_get_type_(const UwMacaroonCaveat* caveat,
    301                                   UwMacaroonCaveatType* type) {
    302   if (caveat == NULL || type == NULL) {
    303     return false;
    304   }
    305 
    306   uint32_t unsigned_int;
    307   if (!uw_macaroon_encoding_decode_uint_(caveat->bytes, caveat->num_bytes,
    308                                          &unsigned_int)) {
    309     return false;
    310   }
    311 
    312   *type = (UwMacaroonCaveatType)unsigned_int;
    313   return is_valid_caveat_type_(*type);
    314 }
    315 
    316 /* === Some internal functions defined in macaroon_caveat_internal.h === */
    317 
    318 bool uw_macaroon_caveat_sign_(const uint8_t* key,
    319                               size_t key_len,
    320                               const UwMacaroonContext* context,
    321                               const UwMacaroonCaveat* caveat,
    322                               uint8_t* mac_tag,
    323                               size_t mac_tag_size) {
    324   if (key == NULL || key_len == 0 || context == NULL || caveat == NULL ||
    325       mac_tag == NULL || mac_tag_size == 0) {
    326     return false;
    327   }
    328 
    329   UwMacaroonCaveatType caveat_type;
    330   if (!uw_macaroon_caveat_get_type_(caveat, &caveat_type) ||
    331       !is_valid_caveat_type_(caveat_type)) {
    332     return false;
    333   }
    334 
    335   // Need to encode the whole caveat as a byte string and then sign it
    336 
    337   // If there is no additional value from the context, just compute the HMAC on
    338   // the current byte string.
    339   uint8_t bstr_cbor_prefix[UW_MACAROON_ENCODING_MAX_UINT_CBOR_LEN] = {0};
    340   size_t bstr_cbor_prefix_len = 0;
    341   if (caveat_type != kUwMacaroonCaveatTypeBleSessionID) {
    342     if (!uw_macaroon_encoding_encode_byte_str_len_(
    343             (uint32_t)(caveat->num_bytes), bstr_cbor_prefix,
    344             sizeof(bstr_cbor_prefix), &bstr_cbor_prefix_len)) {
    345       return false;
    346     }
    347 
    348     UwCryptoHmacMsg messages[] = {
    349         {bstr_cbor_prefix, bstr_cbor_prefix_len},
    350         {caveat->bytes, caveat->num_bytes},
    351     };
    352 
    353     return uw_crypto_hmac_(key, key_len, messages,
    354                            sizeof(messages) / sizeof(messages[0]), mac_tag,
    355                            mac_tag_size);
    356   }
    357 
    358   // If there is additional value from the context.
    359   if (context->ble_session_id == NULL || context->ble_session_id_len == 0) {
    360     return false;
    361   }
    362 
    363   // The length here includes the length of the BLE session ID string.
    364   if (!uw_macaroon_encoding_encode_byte_str_len_(
    365           (uint32_t)(context->ble_session_id_len + caveat->num_bytes),
    366           bstr_cbor_prefix, sizeof(bstr_cbor_prefix), &bstr_cbor_prefix_len)) {
    367     return false;
    368   }
    369 
    370   uint8_t value_cbor_prefix[UW_MACAROON_ENCODING_MAX_UINT_CBOR_LEN] = {0};
    371   size_t value_cbor_prefix_len = 0;
    372   if (!uw_macaroon_encoding_encode_byte_str_len_(
    373           (uint32_t)(context->ble_session_id_len), value_cbor_prefix,
    374           sizeof(value_cbor_prefix), &value_cbor_prefix_len)) {
    375     return false;
    376   }
    377 
    378   UwCryptoHmacMsg messages[] = {
    379       {bstr_cbor_prefix, bstr_cbor_prefix_len},
    380       {caveat->bytes, caveat->num_bytes},
    381       {value_cbor_prefix, value_cbor_prefix_len},
    382       {context->ble_session_id, context->ble_session_id_len},
    383   };
    384 
    385   return uw_crypto_hmac_(key, key_len, messages,
    386                          sizeof(messages) / sizeof(messages[0]), mac_tag,
    387                          mac_tag_size);
    388 }
    389 
    390 static bool update_and_check_expiration_time(
    391     uint32_t current_time,
    392     uint32_t new_expiration_time,
    393     UwMacaroonValidationResult* result) {
    394   if (result->expiration_time > new_expiration_time) {
    395     result->expiration_time = new_expiration_time;
    396   }
    397 
    398   return current_time <= result->expiration_time;
    399 }
    400 
    401 static bool update_delegatee_list(UwMacaroonCaveatType caveat_type,
    402                                   const UwMacaroonCaveat* caveat,
    403                                   uint32_t issued_time,
    404                                   UwMacaroonValidationResult* result) {
    405   if (result->num_delegatees >= MAX_NUM_DELEGATEES || issued_time == 0) {
    406     return false;
    407   }
    408 
    409   UwMacaroonDelegateeType delegatee_type = kUwMacaroonDelegateeTypeNone;
    410   switch (caveat_type) {
    411     case kUwMacaroonCaveatTypeDelegateeUser:
    412       delegatee_type = kUwMacaroonDelegateeTypeUser;
    413       break;
    414 
    415     case kUwMacaroonCaveatTypeDelegateeApp:
    416       delegatee_type = kUwMacaroonDelegateeTypeApp;
    417       break;
    418 
    419     case kUwMacaroonCaveatTypeDelegateeService:
    420       delegatee_type = kUwMacaroonDelegateeTypeService;
    421       break;
    422 
    423     default:
    424       return false;
    425   }
    426 
    427   if (caveat_type != kUwMacaroonCaveatTypeDelegateeUser) {
    428     for (size_t i = 0; i < result->num_delegatees; i++) {
    429       // There must have at most one DelegateeApp or DelegateeService
    430       if (result->delegatees[i].type == delegatee_type) {
    431         return false;
    432       }
    433     }
    434   }
    435 
    436   if (!uw_macaroon_caveat_get_value_bstr_(
    437           caveat, &(result->delegatees[result->num_delegatees].id),
    438           &(result->delegatees[result->num_delegatees].id_len))) {
    439     return false;
    440   }
    441   result->delegatees[result->num_delegatees].type = delegatee_type;
    442   result->delegatees[result->num_delegatees].timestamp = issued_time;
    443   result->num_delegatees++;
    444   return true;
    445 }
    446 
    447 bool uw_macaroon_caveat_validate_(const UwMacaroonCaveat* caveat,
    448                                   const UwMacaroonContext* context,
    449                                   UwMacaroonValidationState* state,
    450                                   UwMacaroonValidationResult* result) {
    451   if (caveat == NULL || context == NULL || state == NULL || result == NULL) {
    452     return false;
    453   }
    454 
    455   uint32_t expiration_time = 0;
    456   uint32_t issued_time = 0;
    457   uint32_t scope = UW_MACAROON_CAVEAT_SCOPE_LOWEST_POSSIBLE;
    458 
    459   UwMacaroonCaveatType caveat_type;
    460   if (!uw_macaroon_caveat_get_type_(caveat, &caveat_type)) {
    461     return false;
    462   }
    463 
    464   switch (caveat_type) {
    465     // The types that always validate
    466     case kUwMacaroonCaveatTypeClientAuthorizationTokenV1:
    467     case kUwMacaroonCaveatTypeServerAuthenticationTokenV1:
    468     case kUwMacaroonCaveatTypeNonce:
    469     case kUwMacaroonCaveatTypeBleSessionID:
    470       return true;
    471 
    472     case kUwMacaroonCaveatTypeDelegationTimestamp:
    473       if (!uw_macaroon_caveat_get_value_uint_(caveat, &issued_time) ||
    474           issued_time < state->issued_time) {
    475         return false;
    476       }
    477       state->issued_time = issued_time;
    478       return true;
    479 
    480     case kUwMacaroonCaveatTypeTTL1Hour:
    481       if (state->issued_time == 0) {
    482         return false;
    483       }
    484       return update_and_check_expiration_time(
    485           context->current_time, state->issued_time + 60 * 60, result);
    486 
    487     case kUwMacaroonCaveatTypeTTL24Hour:
    488       if (state->issued_time == 0) {
    489         return false;
    490       }
    491       return update_and_check_expiration_time(
    492           context->current_time, state->issued_time + 24 * 60 * 60, result);
    493 
    494     // Need to create a list of delegatees
    495     case kUwMacaroonCaveatTypeDelegateeUser:
    496     case kUwMacaroonCaveatTypeDelegateeApp:
    497     case kUwMacaroonCaveatTypeDelegateeService:
    498       return update_delegatee_list(caveat_type, caveat, state->issued_time,
    499                                    result);
    500 
    501     // Time related caveats
    502     case kUwMacaroonCaveatTypeExpirationAbsolute:
    503       if (!uw_macaroon_caveat_get_value_uint_(caveat, &expiration_time)) {
    504         return false;
    505       }
    506       return update_and_check_expiration_time(context->current_time,
    507                                               expiration_time, result);
    508 
    509     // The caveats that update the values of the result object
    510     case kUwMacaroonCaveatTypeScope:
    511       if (!uw_macaroon_caveat_get_value_uint_(caveat, &scope) ||
    512           // Larger value means less priviledge
    513           scope > UW_MACAROON_CAVEAT_SCOPE_LOWEST_POSSIBLE) {
    514         return false;
    515       }
    516       if (scope > (uint32_t)(result->granted_scope)) {
    517         result->granted_scope = (UwMacaroonCaveatScopeType)scope;
    518       }
    519       return true;
    520 
    521     case kUwMacaroonCaveatTypeAppCommandsOnly:
    522       result->weave_app_restricted = true;
    523       return true;
    524 
    525     case kUwMacaroonCaveatTypeLanSessionID:
    526       return uw_macaroon_caveat_get_value_bstr_(
    527           caveat, &(result->lan_session_id), &(result->lan_session_id_len));
    528   }
    529 
    530   return false;
    531 }
    532 
    533 bool uw_macaroon_caveat_get_value_uint_(const UwMacaroonCaveat* caveat,
    534                                         uint32_t* unsigned_int) {
    535   if (caveat == NULL || unsigned_int == NULL) {
    536     return false;
    537   }
    538 
    539   UwMacaroonCaveatType type;
    540   if (!uw_macaroon_caveat_get_type_(caveat, &type)) {
    541     return false;
    542   }
    543   if (type != kUwMacaroonCaveatTypeScope &&
    544       type != kUwMacaroonCaveatTypeExpirationAbsolute &&
    545       type != kUwMacaroonCaveatTypeDelegationTimestamp) {
    546     // Wrong type
    547     return false;
    548   }
    549 
    550   // Skip the portion for CBOR type
    551   size_t offset;
    552   if (!uw_macaroon_encoding_get_item_len_(caveat->bytes, caveat->num_bytes,
    553                                           &offset)) {
    554     return false;
    555   }
    556 
    557   return uw_macaroon_encoding_decode_uint_(
    558       caveat->bytes + offset, caveat->num_bytes - offset, unsigned_int);
    559 }
    560 
    561 bool uw_macaroon_caveat_get_value_bstr_(const UwMacaroonCaveat* caveat,
    562                                         const uint8_t** str,
    563                                         size_t* str_len) {
    564   if (caveat == NULL || str == NULL || str_len == NULL) {
    565     return false;
    566   }
    567 
    568   UwMacaroonCaveatType type;
    569   if (!uw_macaroon_caveat_get_type_(caveat, &type)) {
    570     return false;
    571   }
    572   if (type != kUwMacaroonCaveatTypeNonce &&
    573       type != kUwMacaroonCaveatTypeDelegateeUser &&
    574       type != kUwMacaroonCaveatTypeDelegateeApp &&
    575       type != kUwMacaroonCaveatTypeDelegateeService &&
    576       type != kUwMacaroonCaveatTypeLanSessionID &&
    577       type != kUwMacaroonCaveatTypeClientAuthorizationTokenV1 &&
    578       type != kUwMacaroonCaveatTypeServerAuthenticationTokenV1) {
    579     // Wrong type
    580     return false;
    581   }
    582 
    583   size_t offset;
    584   if (!uw_macaroon_encoding_get_item_len_(caveat->bytes, caveat->num_bytes,
    585                                           &offset)) {
    586     return false;
    587   }
    588 
    589   return uw_macaroon_encoding_decode_byte_str_(
    590       caveat->bytes + offset, caveat->num_bytes - offset, str, str_len);
    591 }
    592 
    593 bool uw_macaroon_caveat_init_validation_state_(
    594     UwMacaroonValidationState* state) {
    595   if (state == NULL) {
    596     return false;
    597   }
    598 
    599   state->issued_time = 0;
    600   return true;
    601 }
    602