Example #1
0
MACAROON_API struct macaroon*
macaroon_add_first_party_caveat(const struct macaroon* N,
                                const unsigned char* predicate, size_t predicate_sz,
                                enum macaroon_returncode* err)
{
    unsigned char hash[MACAROON_HASH_BYTES];
    size_t i;
    size_t sz;
    struct macaroon* M;
    unsigned char* ptr;
    assert(predicate_sz < MACAROON_MAX_STRLEN);

    if (N->num_caveats + 1 > MACAROON_MAX_CAVEATS)
    {
        *err = MACAROON_TOO_MANY_CAVEATS;
        return NULL;
    }

    if (!N->signature.data || N->signature.size != MACAROON_HASH_BYTES)
    {
        *err = MACAROON_INVALID;
        return NULL;
    }

    if (macaroon_hash1(N->signature.data, predicate, predicate_sz, hash) < 0)
    {
        *err = MACAROON_HASH_FAILED;
        return NULL;
    }

    sz = macaroon_body_size(N) + predicate_sz + MACAROON_HASH_BYTES;
    M = macaroon_malloc(N->num_caveats + 1, sz, &ptr);

    if (!M)
    {
        *err = MACAROON_OUT_OF_MEMORY;
        return NULL;
    }

    M->num_caveats = N->num_caveats + 1;
    ptr = copy_slice(&N->location, &M->location, ptr);
    ptr = copy_slice(&N->identifier, &M->identifier, ptr);

    for (i = 0; i < N->num_caveats; ++i)
    {
        ptr = copy_slice(&N->caveats[i].cid, &M->caveats[i].cid, ptr);
        ptr = copy_slice(&N->caveats[i].vid, &M->caveats[i].vid, ptr);
        ptr = copy_slice(&N->caveats[i].cl,  &M->caveats[i].cl,  ptr);
    }

    ptr = copy_to_slice(predicate, predicate_sz,
                        &M->caveats[M->num_caveats - 1].cid, ptr);
    ptr = copy_to_slice(hash, MACAROON_HASH_BYTES, &M->signature, ptr);
    VALIDATE(M);
    return M;
}
Example #2
0
/* Insert slices into a goal branch.
 * The inserted slices are copies of the elements of prototypes).
 * Each slice is inserted at a position that corresponds to its predefined rank.
 * @param si identifies starting point of insertion
 * @param prototypes contains the prototypes whose copies are inserted
 * @param nr_prototypes number of elements of array prototypes
 */
static void goal_branch_insert_slices_nested(slice_index si,
                                             slice_index const prototypes[],
                                             unsigned int nr_prototypes)
{
  TraceFunctionEntry(__func__);
  TraceFunctionParam("%u",si);
  TraceFunctionParam("%u",nr_prototypes);
  TraceFunctionParamListEnd();

  {
    slice_type const prototype_type = SLICE_TYPE(prototypes[0]);
    unsigned int prototype_rank = get_goal_slice_rank(prototype_type);

    if (prototype_rank==no_goal_slice_type)
    {
      if (nr_prototypes>1)
        goal_branch_insert_slices_nested(si,prototypes+1,nr_prototypes-1);
    }
    else
      do
      {
        slice_index const next = SLICE_NEXT1(si);
        if (SLICE_TYPE(next)==STProxy)
          si = next;
        else if (SLICE_TYPE(next)==STOr
                 || SLICE_TYPE(next)==STAnd)
        {
          goal_branch_insert_slices_nested(SLICE_NEXT1(next),
                                           prototypes,nr_prototypes);
          goal_branch_insert_slices_nested(SLICE_NEXT2(next),
                                           prototypes,nr_prototypes);
          break;
        }
        else
        {
          unsigned int const rank_next = get_goal_slice_rank(SLICE_TYPE(next));
          if (rank_next==no_goal_slice_type)
            break;
          else if (rank_next>prototype_rank)
          {
            slice_index const copy = copy_slice(prototypes[0]);
            pipe_append(si,copy);
            if (nr_prototypes>1)
              goal_branch_insert_slices_nested(copy,prototypes+1,nr_prototypes-1);
            break;
          }
          else
            si = next;
        }
      } while (prototype_type!=SLICE_TYPE(si));
  }

  TraceFunctionExit(__func__);
  TraceFunctionResultEnd();
}
Example #3
0
/* Callback to stip_spin_off_testers
 * Spin a tester slice off a fork slice
 * @param si identifies the testing pipe slice
 * @param st address of structure representing traversal
 */
void stip_spin_off_testers_fork(slice_index si, stip_structure_traversal *st)
{
  TraceFunctionEntry(__func__);
  TraceFunctionParam("%u",si);
  TraceFunctionParamListEnd();

  SLICE_TESTER(si) = copy_slice(si);
  stip_traverse_structure_children(si,st);
  link_to_branch(SLICE_TESTER(si),SLICE_TESTER(SLICE_NEXT1(si)));
  SLICE_NEXT2(SLICE_TESTER(si)) = SLICE_TESTER(SLICE_NEXT2(si));

  TraceFunctionExit(__func__);
  TraceFunctionResultEnd();
}
Example #4
0
/* End copying on the visited slice, by moving it to the copy and linking it
 * to a proxy slice that takes its original place
 * @param si visited slice
 * @param st structure representing the copying traversal
 */
static void move_and_stop_copying(slice_index si, stip_structure_traversal *st)
{
  stip_deep_copies_type * const copies = st->param;

  TraceFunctionEntry(__func__);
  TraceFunctionParam("%u",si);
  TraceFunctionParamListEnd();

  assert((*copies)[si]==no_slice);
  (*copies)[si] = copy_slice(si);
  pipe_substitute(si,alloc_proxy_slice());
  link_to_branch((*copies)[si],si);

  TraceFunctionExit(__func__);
  TraceFunctionResultEnd();
}
Example #5
0
/* Create a shallow copy of the visited fork slice
 * @param si visited slice
 * @param st structure representing the copying traversal
 */
static void copy_shallow(slice_index si, stip_structure_traversal *st)
{
  stip_deep_copies_type * const copies = st->param;

  TraceFunctionEntry(__func__);
  TraceFunctionParam("%u",si);
  TraceFunctionParamListEnd();

  assert((*copies)[si]==no_slice);
  (*copies)[si] = copy_slice(si);

  stip_traverse_structure_children_pipe(si,st);

  if (SLICE_NEXT1(si)!=no_slice)
    link_to_branch((*copies)[si],(*copies)[SLICE_NEXT1(si)]);

  TraceFunctionExit(__func__);
  TraceFunctionResultEnd();
}
Example #6
0
/* Add the copy of a slice into the set play branch
 * @param si slice index
 * @param st state of traversal
 */
static void copy_to_setplay(slice_index si, stip_structure_traversal *st)
{
  spin_off_state_type * const state = st->param;

  TraceFunctionEntry(__func__);
  TraceFunctionParam("%u",si);
  TraceFunctionParamListEnd();

  stip_traverse_structure_children_pipe(si,st);
  TraceValue("%u",state->spun_off[SLICE_NEXT1(si)]);
  TraceEOL();

  state->spun_off[si] = copy_slice(si);
  link_to_branch(state->spun_off[si],state->spun_off[SLICE_NEXT1(si)]);
  TraceValue("%u",state->spun_off[si]);
  TraceEOL();

  TraceFunctionExit(__func__);
  TraceFunctionResultEnd();
}
Example #7
0
/* Shorten a help branch by 1 half move
 * @param identifies entry slice of branch to be shortened
 */
void help_branch_shorten(slice_index adapter)
{
  slice_index const next = SLICE_NEXT1(adapter);

  TraceFunctionEntry(__func__);
  TraceFunctionParam("%u",adapter);
  TraceFunctionParamListEnd();

  assert(SLICE_TYPE(adapter)==STHelpAdapter);

  {
    /* find the new spot for adapter by inserting a copy */
    slice_index const prototype = copy_slice(adapter);
    help_branch_insert_slices(next,&prototype,1);
  }

  {
    /* move adapter to its new spot */
    slice_index const copy = branch_find_slice(STHelpAdapter,
                                               next,
                                               stip_traversal_context_help);
    assert(copy!=no_slice);
    pipe_link(SLICE_PREV(adapter),next);
    pipe_append(copy,adapter);
    pipe_remove(copy);
  }

  /* adjust the length and min_length members */
  --SLICE_U(adapter).branch.length;
  if (SLICE_U(adapter).branch.min_length<=0)
    increase_min_length(adapter);
  --SLICE_U(adapter).branch.min_length;
  branch_shorten_slices(next,STHelpAdapter,stip_traversal_context_help);

  TraceFunctionExit(__func__);
  TraceFunctionResultEnd();
}
Example #8
0
/* Spin a copy off a conditional pipe to add it to the root or set play branch
 * @param si identifies (non-root) slice
 * @param st address of structure representing traversal
 */
void conditional_pipe_spin_off_copy(slice_index si,
                                    stip_structure_traversal *st)
{
  spin_off_state_type * const state = st->param;

  TraceFunctionEntry(__func__);
  TraceFunctionParam("%u",si);
  TraceFunctionParamListEnd();

  state->spun_off[si] = copy_slice(si);

  stip_traverse_structure_children_pipe(si,st);

  if (state->spun_off[SLICE_NEXT1(si)]==no_slice)
  {
    dealloc_slice(state->spun_off[si]);
    state->spun_off[si] = no_slice;
  }
  else
    link_to_branch(state->spun_off[si],state->spun_off[SLICE_NEXT1(si)]);

  TraceFunctionExit(__func__);
  TraceFunctionResultEnd();
}
Example #9
0
MACAROON_API struct macaroon*
macaroon_add_third_party_caveat_raw(const struct macaroon* N,
                                    const unsigned char* location, size_t location_sz,
                                    const unsigned char* key, size_t key_sz,
                                    const unsigned char* id, size_t id_sz,
                                    enum macaroon_returncode* err)
{
    unsigned char new_sig[MACAROON_HASH_BYTES];
    unsigned char enc_nonce[MACAROON_SECRET_NONCE_BYTES];
    unsigned char enc_plaintext[MACAROON_SECRET_TEXT_ZERO_BYTES + MACAROON_HASH_BYTES];
    unsigned char enc_ciphertext[MACAROON_SECRET_BOX_ZERO_BYTES + MACAROON_HASH_BYTES];
    unsigned char vid[VID_NONCE_KEY_SZ];
    size_t i;
    size_t sz;
    struct macaroon* M;
    unsigned char* ptr;
    assert(location_sz < MACAROON_MAX_STRLEN);
    assert(id_sz < MACAROON_MAX_STRLEN);
    assert(key_sz == MACAROON_SUGGESTED_SECRET_LENGTH);
    VALIDATE(N);

    if (N->num_caveats + 1 > MACAROON_MAX_CAVEATS)
    {
        *err = MACAROON_TOO_MANY_CAVEATS;
        return NULL;
    }

    /*
     * note that MACAROON_HASH_BYTES is necessarily the same as
     * MACAROON_SECRET_KEY_BYTES, so the signature is also good to use
      * as an encoding key
     */
    if (!N->signature.data || N->signature.size != MACAROON_HASH_BYTES)
    {
        *err = MACAROON_INVALID;
        return NULL;
    }

    macaroon_randombytes(enc_nonce, sizeof(enc_nonce));
    macaroon_memzero(enc_plaintext, sizeof(enc_plaintext));
    macaroon_memzero(enc_ciphertext, sizeof(enc_ciphertext));

    /* now encrypt the key to give us vid */
    memmove(enc_plaintext + MACAROON_SECRET_TEXT_ZERO_BYTES, key,
            key_sz < MACAROON_HASH_BYTES ? key_sz : MACAROON_HASH_BYTES);

    if (macaroon_secretbox(N->signature.data, enc_nonce, enc_plaintext,
                MACAROON_SECRET_TEXT_ZERO_BYTES + MACAROON_HASH_BYTES,
                enc_ciphertext) < 0)
    {
        *err = MACAROON_HASH_FAILED;
        return NULL;
    }

    /* copy the (nonce, vid) pair into vid */
    memmove(vid, enc_nonce, MACAROON_SECRET_NONCE_BYTES);
    memmove(vid           + MACAROON_SECRET_NONCE_BYTES,
            enc_ciphertext + MACAROON_SECRET_BOX_ZERO_BYTES,
            VID_NONCE_KEY_SZ - MACAROON_SECRET_NONCE_BYTES);

    /* calculate the new signature */
    if (macaroon_hash2(N->signature.data, vid, VID_NONCE_KEY_SZ, id, id_sz, new_sig) < 0)
    {
        *err = MACAROON_HASH_FAILED;
        return NULL;
    }

    sz = macaroon_body_size(N)
       + id_sz
       + VID_NONCE_KEY_SZ
       + location_sz
       + MACAROON_HASH_BYTES;
    M = macaroon_malloc(N->num_caveats + 1, sz, &ptr);

    if (!M)
    {
        *err = MACAROON_OUT_OF_MEMORY;
        return NULL;
    }

    M->num_caveats = N->num_caveats + 1;
    ptr = copy_slice(&N->location, &M->location, ptr);
    ptr = copy_slice(&N->identifier, &M->identifier, ptr);

    for (i = 0; i < N->num_caveats; ++i)
    {
        ptr = copy_slice(&N->caveats[i].cid, &M->caveats[i].cid, ptr);
        ptr = copy_slice(&N->caveats[i].vid, &M->caveats[i].vid, ptr);
        ptr = copy_slice(&N->caveats[i].cl,  &M->caveats[i].cl,  ptr);
    }

    ptr = copy_to_slice(id, id_sz, &M->caveats[M->num_caveats - 1].cid, ptr);
    ptr = copy_to_slice(vid, VID_NONCE_KEY_SZ, &M->caveats[M->num_caveats - 1].vid, ptr);
    ptr = copy_to_slice(location, location_sz, &M->caveats[M->num_caveats - 1].cl, ptr);
    ptr = copy_to_slice(new_sig, MACAROON_HASH_BYTES, &M->signature, ptr);
    VALIDATE(M);
    return M;
}