Пример #1
0
/**
 * Escribe sobre el output_stream el contenido del
 * input_stream codificado en base 64
 */
int encode(FILE* input_stream, FILE* output_stream) {
	char input_buffer[3];
	char output_buffer[4];

	set_endianess();

	int bytes_read = fread(input_buffer, sizeof(char), 3, input_stream);
	while (bytes_read > 0) {
		if (bytes_read < 3)
			input_buffer[2] = 0;
		if (bytes_read < 2)
			input_buffer[1] = 0;

		if (!encode_to_base64(input_buffer, output_buffer))
			return ENCODE_ERROR;

		add_padding(bytes_read, output_buffer);

		int bytes_wrote = fwrite(output_buffer, sizeof(char), 4, output_stream);

		if (bytes_wrote != 4)
			return WRITE_ERROR;

		bytes_read = fread(input_buffer, sizeof(char), 3, input_stream);
	}

	return 0;
}
Пример #2
0
 /**
  * Add role to buffer.
  *
  * @param member Relation member object where the length of the role
  *               will be set.
  * @param role The role.
  * @param length Length of role (without \0 termination).
  * @throws std:length_error If role is longer than osmium::max_osm_string_length
  */
 void add_role(osmium::RelationMember& member, const char* role, const size_t length) {
     if (length > osmium::max_osm_string_length) {
         throw std::length_error("OSM relation member role is too long");
     }
     member.set_role_size(osmium::string_size_type(length) + 1);
     add_size(append(role, osmium::memory::item_size_type(length)) + append_zero());
     add_padding(true);
 }
Пример #3
0
 void add_text(osmium::ChangesetComment& comment, const char* text, const size_t length) {
     // XXX There is no limit on the length of a comment text. We
     // limit it here to 2^16-2 characters, because that's all that
     // will fit into our internal data structure. This is not ideal,
     // and will have to be discussed and cleared up.
     if (length > std::numeric_limits<osmium::string_size_type>::max() - 1) {
         throw std::length_error("OSM changeset comment is too long");
     }
     comment.set_text_size(osmium::string_size_type(length) + 1);
     add_size(append(text, osmium::memory::item_size_type(length)) + append_zero());
     add_padding(true);
 }
Пример #4
0
/* RFC 3542, 10.2

   This function returns the updated total length taking into account
   adding an option with length 'len' and alignment 'align'.  If
   EXTBUF is not NULL then, in addition to returning the length, the
   function inserts any needed pad option, initializes the option
   (setting the type and length fields) and returns a pointer to the
   location for the option content in databufp.  If the option does
   not fit in the extension header buffer the function returns -1.  */
int
inet6_opt_append (void *extbuf, socklen_t extlen, int offset, uint8_t type,
		  socklen_t len, uint8_t align, void **databufp)
{
  /* Check minimum offset.  */
  if (offset < sizeof (struct ip6_hbh))
    return -1;

  /* One cannot add padding options.  */
  if (type == IP6OPT_PAD1 || type == IP6OPT_PADN)
    return -1;

  /* The option length must fit in one octet.  */
  if (len > 255)
    return -1;

  /* The alignment can only by 1, 2, 4, or 8 and must not exceed the
     option length.  */
  if (align == 0 || align > 8 || (align & (align - 1)) != 0 || align > len)
    return -1;

  /* Determine the needed padding for alignment.  Following the
     current content of the buffer we have the is the IPv6 option type
     and length, followed immediately by the data.  The data has the
     alignment constraints.  Therefore padding must be inserted in the
     form of padding options before the new option. */
  int data_offset = offset + sizeof (struct ip6_opt);
  int npad = (align - data_offset % align) & (align - 1);

  if (extbuf != NULL)
    {
      /* Now we can check whether the buffer is large enough.  */
      if (data_offset + npad + len > extlen)
	return -1;

      add_padding (extbuf, offset, npad);

      offset += npad;

      /* Now prepare the option itself.  */
      struct ip6_opt *opt = (struct ip6_opt *) ((uint8_t *) extbuf + offset);

      opt->ip6o_type = type;
      opt->ip6o_len = len;

      *databufp = opt + 1;
    }
  else
    offset += npad;

  return offset + sizeof (struct ip6_opt) + len;
}
Пример #5
0
static int format_data(sc_card_t *card, const struct iso_sm_ctx *ctx,
        const u8 *data, size_t datalen,
        struct sc_asn1_entry *formatted_encrypted_data_entry,
        u8 **formatted_data, size_t *formatted_data_len)
{
    int r;
    u8 *pad_data = NULL;
    size_t pad_data_len = 0;

    if (!ctx || !formatted_data || !formatted_data_len) {
        r = SC_ERROR_INVALID_ARGUMENTS;
        goto err;
    }

    r = add_padding(ctx, data, datalen, &pad_data);
    if (r < 0) {
        sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not add padding to data: %s",
                sc_strerror(r));
        goto err;
    }
    pad_data_len = r;

    bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Data to encrypt", pad_data, pad_data_len);
    r = ctx->encrypt(card, ctx, pad_data, pad_data_len, formatted_data);
    if (r < 0) {
        sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not encrypt the data");
        goto err;
    }
    bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Cryptogram", *formatted_data, r);

    r = prefix_buf(ctx->padding_indicator, *formatted_data, r, formatted_data);
    if (r < 0) {
        sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not prepend padding indicator to formatted "
                "data: %s", sc_strerror(r));
        goto err;
    }

    *formatted_data_len = r;
    sc_format_asn1_entry(formatted_encrypted_data_entry,
            *formatted_data, formatted_data_len, SC_ASN1_PRESENT);

    r = SC_SUCCESS;

err:
    if (pad_data) {
        sc_mem_clear(pad_data, pad_data_len);
        free(pad_data);
    }

    return r;
}
Пример #6
0
int		print_str_padded(char *str, t_vars *vars, char *prefix)
{
	size_t	len_str;
	int		padding;
	char	*string;

	string = ft_strdup(str);

	len_str = ft_strlen(string);
	padding = vars->padding - len_str;
	if (prefix)
		padding -= ft_strlen(prefix);
	if (padding > 0 && HAS_FLAG_ZERO(vars->flags))
		string = add_padding(string, (size_t)padding, vars);
	if (prefix)
		ft_str_renew(&string, ft_strjoin(prefix, string)); // not opti
	if (padding > 0 && !HAS_FLAG_ZERO(vars->flags))
		string = add_padding(string, (size_t)padding, vars);
	len_str = ft_strlen(string);
	ft_putstr(string);
	vars->precision = -1;
	return (len_str);
}
Пример #7
0
// see core.h
kssl_error_code kssl_error(DWORD id,
                           BYTE error,
                           BYTE **response,
                           int *response_len) {
  kssl_header e;
  int offset = 0;
  int size = KSSL_HEADER_SIZE + KSSL_OPCODE_ITEM_SIZE + KSSL_ERROR_ITEM_SIZE;
  BYTE *resp;

  // The operation will always be padded to KSSL_PAD_TO +
  // KSSL_ITEM_HEADER_SIZE bytes

  int padding_size = 0;
  if (size < KSSL_PAD_TO) {
    padding_size = KSSL_PAD_TO - size;
  }

  if (response == NULL || response_len == NULL) {
    return KSSL_ERROR_INTERNAL;
  }

  size += padding_size + KSSL_ITEM_HEADER_SIZE;

  // The memory is calloced here to ensure that it is all zero. This is
  // important because the padding added below is done by just adding a
  // KSSL_ITEM at the end of the message stating that it has N bytes of
  // padding.
  
  resp = (BYTE *)calloc(size, 1);
  if (resp == NULL) {
    return KSSL_ERROR_INTERNAL;
  }

  e.version_maj = KSSL_VERSION_MAJ;
  e.version_min = KSSL_VERSION_MIN;
  e.length  = size - KSSL_HEADER_SIZE;
  e.id      = id;

  flatten_header(&e, resp, &offset);
  flatten_item_byte(KSSL_TAG_OPCODE, KSSL_OP_ERROR, resp, &offset);
  flatten_item_byte(KSSL_TAG_PAYLOAD, error, resp, &offset);
  add_padding(padding_size, resp, &offset);

  *response = resp;
  *response_len = size;

  return KSSL_ERROR_NONE;
}
Пример #8
0
static int format_head(const struct iso_sm_ctx *ctx, const sc_apdu_t *apdu,
        u8 **formatted_head)
{
    if (!apdu || !formatted_head)
        return SC_ERROR_INVALID_ARGUMENTS;

    u8 *p = realloc(*formatted_head, 4);
    if (!p)
        return SC_ERROR_OUT_OF_MEMORY;

    p[0] = apdu->cla;
    p[1] = apdu->ins;
    p[2] = apdu->p1;
    p[3] = apdu->p2;
    *formatted_head = p;

    return add_padding(ctx, *formatted_head, 4, formatted_head);
}
Пример #9
0
/* RFC 3542, 10.3

   This function returns the updated total length taking into account
   the final padding of the extension header to make it a multiple of
   8 bytes.  If EXTBUF is not NULL the function also initializes the
   option by inserting a Pad1 or PadN option of the proper length.  */
int
inet6_opt_finish (void *extbuf, socklen_t extlen, int offset)
{
  /* Check minimum offset.  */
  if (offset < sizeof (struct ip6_hbh))
    return -1;

  /* Required padding at the end.  */
  int npad = (8 - (offset & 7)) & 7;

  if (extbuf != NULL)
    {
      /* Make sure the buffer is large enough.  */
      if (offset + npad > extlen)
	return -1;

      add_padding (extbuf, offset, npad);
    }

  return offset + npad;
}
Пример #10
0
void c_typecheck_baset::typecheck_compound_type(struct_union_typet &type)
{
  struct_union_typet::componentst &components=type.components();

  // mark bit-fields
  for(struct_union_typet::componentst::iterator
      it=components.begin();
      it!=components.end();
      it++)
    if(it->type().id()==ID_c_bitfield)
    {
      it->set_is_bit_field(true);
      typet tmp=it->type().subtype();
      typecheck_type(tmp);
      it->set_bit_field_type(tmp);
    }

  // check subtypes
  for(struct_union_typet::componentst::iterator
      it=components.begin();
      it!=components.end();
      it++)
    typecheck_type(it->type());

  unsigned anon_member_counter=0;

  // scan for anonymous members, and name them
  for(struct_union_typet::componentst::iterator
      it=components.begin();
      it!=components.end();
      it++)
  {
    if(it->get_name()!=irep_idt()) continue;

    it->set_name("$anon"+i2string(anon_member_counter++));
    it->set_anonymous(true);
  }

  // scan for duplicate members

  {
    hash_set_cont<irep_idt, irep_id_hash> members;

    for(struct_union_typet::componentst::iterator
        it=components.begin();
        it!=components.end();
        it++)
    {
      if(!members.insert(it->get_name()).second)
      {
        // we do nothing (as gcc won't complain)
      }
    }
  }
  
  // We allow an incomplete (C99) array as _last_ member!
  // Zero-length is allowed everywhere.

  if(type.id()==ID_struct)
  {
    for(struct_union_typet::componentst::iterator
        it=components.begin();
        it!=components.end();
        it++)
    {
      typet &type=it->type();
    
      if(type.id()==ID_array &&
         to_array_type(type).is_incomplete())
      {
        // needs to be last member
        if(it!=--components.end())
        {
          err_location(*it);
          throw "flexible struct member must be last member";
        }
        
        // make it zero-length
        type.id(ID_array);
        type.set(ID_size, gen_zero(index_type()));
      }
    }  
  }

  // we may add some minimal padding inside structs (not unions)
  // unless there is an attribute that says that the struct is
  // 'packed'

  if(type.id()==ID_struct)
    add_padding(to_struct_type(type), *this);

  // finally, check _Static_assert inside the compound
  for(struct_union_typet::componentst::iterator
      it=components.begin();
      it!=components.end();
      ) // no it++
  {
    if(it->id()==ID_code && it->get(ID_statement)==ID_static_assert)
    {
      assert(it->operands().size()==2);
      exprt &assertion=it->op0();
      typecheck_expr(assertion);
      typecheck_expr(it->op1());
      assertion.make_typecast(bool_typet());
      make_constant(assertion);
      
      if(assertion.is_false())
      {
        err_location(*it);
        throw "failed _Static_assert";
      }
      else if(!assertion.is_true())
      {
        // should warn/complain
      }
      
      it=components.erase(it);
    }
    else
      it++;
  }  
}
Пример #11
0
 /**
  * Add role to buffer.
  *
  * @param member Relation member object where the length of the role
  *               will be set.
  * @param role The role.
  * @param length Length of role string including \0 termination.
  */
 void add_role(osmium::RelationMember& member, const char* role, const string_size_type length) {
     member.set_role_size(length);
     add_size(append(role, length));
     add_padding(true);
 }
Пример #12
0
 ~ChangesetDiscussionBuilder() {
     assert(!m_comment && "You have to always call both add_comment() and then add_comment_text() in that order for each comment!");
     add_padding();
 }
Пример #13
0
void c_typecheck_baset::typecheck_compound_body(
  struct_union_typet &type)
{
  struct_union_typet::componentst &components=type.components();

  struct_union_typet::componentst old_components;
  old_components.swap(components);

  // We get these as declarations!
  for(auto &decl : old_components)
  {
    // the arguments are member declarations or static assertions
    assert(decl.id()==ID_declaration);

    ansi_c_declarationt &declaration=
      to_ansi_c_declaration(static_cast<exprt &>(decl));

    if(declaration.get_is_static_assert())
    {
      struct_union_typet::componentt new_component;
      new_component.id(ID_static_assert);
      new_component.add_source_location()=declaration.source_location();
      new_component.operands().swap(declaration.operands());
      assert(new_component.operands().size()==2);
      components.push_back(new_component);
    }
    else
    {
      // do first half of type
      typecheck_type(declaration.type());
      make_already_typechecked(declaration.type());

      for(const auto &declarator : declaration.declarators())
      {
        struct_union_typet::componentt new_component;

        new_component.add_source_location()=
          declarator.source_location();
        new_component.set(ID_name, declarator.get_base_name());
        new_component.set(ID_pretty_name, declarator.get_base_name());
        new_component.type()=declaration.full_type(declarator);

        typecheck_type(new_component.type());

        if(!is_complete_type(new_component.type()) &&
           (new_component.type().id()!=ID_array ||
            !to_array_type(new_component.type()).is_incomplete()))
        {
          error().source_location=new_component.type().source_location();
          error() << "incomplete type not permitted here" << eom;
          throw 0;
        }

        components.push_back(new_component);
      }
    }
  }

  unsigned anon_member_counter=0;

  // scan for anonymous members, and name them
  for(auto &member : components)
  {
    if(member.get_name()!=irep_idt())
      continue;

    member.set_name("$anon"+std::to_string(anon_member_counter++));
    member.set_anonymous(true);
  }

  // scan for duplicate members

  {
    std::unordered_set<irep_idt, irep_id_hash> members;

    for(struct_union_typet::componentst::iterator
        it=components.begin();
        it!=components.end();
        it++)
    {
      if(!members.insert(it->get_name()).second)
      {
        error().source_location=it->source_location();
        error() << "duplicate member '" << it->get_name() << '\'' << eom;
        throw 0;
      }
    }
  }

  // We allow an incomplete (C99) array as _last_ member!
  // Zero-length is allowed everywhere.

  if(type.id()==ID_struct ||
     type.id()==ID_union)
  {
    for(struct_union_typet::componentst::iterator
        it=components.begin();
        it!=components.end();
        it++)
    {
      typet &c_type=it->type();

      if(c_type.id()==ID_array &&
         to_array_type(c_type).is_incomplete())
      {
        // needs to be last member
        if(type.id()==ID_struct && it!=--components.end())
        {
          error().source_location=it->source_location();
          error() << "flexible struct member must be last member" << eom;
          throw 0;
        }

        // make it zero-length
        c_type.id(ID_array);
        c_type.set(ID_size, from_integer(0, index_type()));
      }
    }
  }

  // We may add some minimal padding inside and at
  // the end of structs and
  // as additional member for unions.

  if(type.id()==ID_struct)
    add_padding(to_struct_type(type), *this);
  else if(type.id()==ID_union)
    add_padding(to_union_type(type), *this);

  // Now remove zero-width bit-fields, these are just
  // for adjusting alignment.
  for(struct_typet::componentst::iterator
      it=components.begin();
      it!=components.end();
      ) // blank
  {
    if(it->type().id()==ID_c_bit_field &&
       to_c_bit_field_type(it->type()).get_width()==0)
      it=components.erase(it);
    else
      it++;
  }

  // finally, check _Static_assert inside the compound
  for(struct_union_typet::componentst::iterator
      it=components.begin();
      it!=components.end();
      ) // no it++
  {
    if(it->id()==ID_static_assert)
    {
      assert(it->operands().size()==2);
      exprt &assertion=it->op0();
      typecheck_expr(assertion);
      typecheck_expr(it->op1());
      assertion.make_typecast(bool_typet());
      make_constant(assertion);

      if(assertion.is_false())
      {
        error().source_location=it->source_location();
        error() << "failed _Static_assert" << eom;
        throw 0;
      }
      else if(!assertion.is_true())
      {
        // should warn/complain
      }

      it=components.erase(it);
    }
    else
      it++;
  }
}
 void add_role(osmium::RelationMember* member, const char* role) {
     member->set_role_size(std::strlen(role) + 1);
     add_size(append(role));
     add_padding(true);
 }
Пример #15
0
static bool create_onion(const secp256k1_pubkey pubkey[],
			 char *const msg[],
			 size_t num,
			 struct onion *onion)
{
	int i;
	struct seckey seckeys[MAX_HOPS];
	struct onion_pubkey pubkeys[MAX_HOPS];
	struct enckey enckeys[MAX_HOPS];
	struct hmackey hmackeys[MAX_HOPS];
	struct iv ivs[MAX_HOPS];
	struct iv pad_ivs[MAX_HOPS];
	HMAC_CTX padding_hmac[MAX_HOPS];
	struct hop padding[MAX_HOPS];
	size_t junk_hops;
	secp256k1_context *ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
	bool ok = false;

	if (num > MAX_HOPS)
		goto fail;

	/* FIXME: I think it would be safe to reuse a single disposable key
	 * here? */
	/* First generate all the keys. */
	for (i = 0; i < num; i++) {
		unsigned char secret[32];

		gen_keys(ctx, &seckeys[i], &pubkeys[i]);


		/* Make shared secret. */
		if (!secp256k1_ecdh(ctx, secret, &pubkey[i], seckeys[i].u.u8))
			goto fail;

		hmackeys[i] = hmackey_from_secret(memcheck(secret, 32));
		enckeys[i] = enckey_from_secret(secret);
		ivs_from_secret(secret, &ivs[i], &pad_ivs[i]);
	}

	/*
	 * Building the onion is a little tricky.
	 *
	 * First, there is the padding.  That's generated by previous nodes,
	 * and "decrypted" by the others.  So we have to generate that
	 * forwards.
	 */
	for (i = 0; i < num; i++) {
		if (i > 0) {
			/* Previous node decrypts padding before passing on. */
			aes_decrypt(padding, padding, sizeof(struct hop)*(i-1),
				    &enckeys[i-1], &ivs[i-1]);
			memmove(padding + 1, padding,
				sizeof(struct hop)*(i-1));
		}
		/* And generates more padding for next node. */
		add_padding(&padding[0], &enckeys[i-1], &pad_ivs[i-1]);
		HMAC_CTX_init(&padding_hmac[i]);
		HMAC_Init_ex(&padding_hmac[i],
			     hmackeys[i].k.u.u8, sizeof(hmackeys[i].k),
			     EVP_sha256(), NULL);
		HMAC_Update(&padding_hmac[i],
			    memcheck((unsigned char *)padding,
				     i * sizeof(struct hop)),
			    i * sizeof(struct hop));
	}

	/*
	 * Now the normal onion is generated backwards.
	 */

	/* Unused hops filled with random, so even recipient can't tell
	 * how many were used. */
	junk_hops = MAX_HOPS - num;
	random_bytes(onion->hop, junk_hops * sizeof(struct hop));

	for (i = num - 1; i >= 0; i--) {
		size_t other_hops, len;
		struct hop *myhop;

		other_hops = num - i - 1 + junk_hops;

		/* Our entry is at tail of onion. */
		myhop = onion->hop + other_hops;

		/* Now populate our hop. */
		myhop->pubkey = pubkeys[i];
		/* Set message. */
		assert(strlen(msg[i]) < MESSAGE_SIZE);
		memset(myhop->msg, 0, MESSAGE_SIZE);
		strcpy((char *)myhop->msg, msg[i]);

		/* Encrypt whole thing, including our message, but we
		 * aware it will be offset by the prepended padding. */
		if (!aes_encrypt_offset(i * sizeof(struct hop),
					onion, onion,
					other_hops * sizeof(struct hop)
					+ sizeof(myhop->msg),
					&enckeys[i], &ivs[i]))
			goto fail;

		/* HMAC covers entire thing except hmac itself. */
		len = (other_hops + 1)*sizeof(struct hop) - sizeof(myhop->hmac);
		HMAC_Update(&padding_hmac[i],
			    memcheck((unsigned char *)onion, len), len);
		HMAC_Final(&padding_hmac[i], myhop->hmac.u.u8, NULL);
	}

	ok = true;
fail:
	secp256k1_context_destroy(ctx);
	return ok;
}
Пример #16
0
int get_PSRFITS_rawblock(float *fdata, struct spectra_info *s, int *padding)
// This routine reads a single block (i.e subint) from the input files
// which contain raw data in PSRFITS format.  If padding is
// returned as 1, then padding was added and statistics should not be
// calculated.  Return 1 on success.
{
    int numtopad = 0, numtoread, status = 0, anynull;
    float *fdataptr = fdata;

    fdataptr = fdata + numbuffered * s->num_channels;
    // numtoread is always this size since we need to read
    // full PSRFITS subints...
    numtoread = s->spectra_per_subint;

    // If our buffer array is offset from last time,
    // copy the previously offset part into the beginning.
    // New data comes after the old data in the buffer.
    if (numbuffered)
        memcpy((char *) fdata, (char *) (fdata + numtoread * s->num_channels),
               numbuffered * s->num_channels * sizeof(float));

    // Make sure our current file number is valid
    if (cur_file >= s->num_files)
        return 0;

    // Read a subint of data from the DATA col
    if (cur_subint <= s->num_subint[cur_file]) {
        double offs_sub = 0.0;
        if (!offs_sub_are_zero) {
            // Read the OFFS_SUB column value in case there were dropped blocks
            fits_read_col(s->fitsfiles[cur_file], TDOUBLE,
                          s->offs_sub_col, cur_subint, 1L, 1L,
                          0, &offs_sub, &anynull, &status);
            // Set new_spec to proper value, accounting for possibly
            // missing initial rows of data and/or combining observations
            // Note: need to remove start_subint because that was already put
            // into start_spec.  This is important if initial rows are gone.
            new_spec = s->start_spec[cur_file] +
                roundl((offs_sub - (s->start_subint[cur_file] + 0.5)
                        * s->time_per_subint) / s->dt);
        } else {
            new_spec = s->start_spec[cur_file] +
                (cur_subint - 1) * s->spectra_per_subint;
        }

        //printf("cur/new_spec = %lld, %lld  s->start_spec[cur_file] = %lld\n",
        //       cur_spec, new_spec, s->start_spec[cur_file]);

        // The following determines if there were lost blocks, or if
        // we are putting different observations together so that
        // the blocks are not aligned
        if (new_spec == cur_spec + numbuffered) {
            // if things look good, with no missing blocks, read the data
            get_PSRFITS_subint(fdataptr, cdatabuffer, s);
            cur_subint++;
            goto return_block;
        } else {
            goto padding_block;
        }
    } else {
        // We are going to move to the next file, so update
        // new_spec to be the starting spectra from the next file
        // so we can see if any padding is necessary
        if (cur_file < s->num_files - 1)
            new_spec = s->start_spec[cur_file + 1];
        else
            new_spec = cur_spec + numbuffered;
    }

    if (new_spec == cur_spec + numbuffered) {
        // No padding is necessary, so switch files
        cur_file++;
        cur_subint = 1;
        return get_PSRFITS_rawblock(fdata, s, padding);
    } else {                    // add padding
        goto padding_block;
    }

  padding_block:
    if (new_spec < cur_spec) {
        // Files out of order?  Shouldn't get here.
        fprintf(stderr, "Error!:  Current subint has earlier time than previous!\n\n"
                "\tfilename = '%s', subint = %d\n"
                "\tcur_spec = %lld  new_spec = %lld\n",
                s->filenames[cur_file], cur_subint, cur_spec, new_spec);
        exit(1);
    }
    numtopad = new_spec - cur_spec;
    // Don't add more than 1 block and if buffered, then realign the buffer
    if (numtopad > (s->spectra_per_subint - numbuffered))
        numtopad = s->spectra_per_subint - numbuffered;
    add_padding(fdataptr, s->padvals, s->num_channels, numtopad);
    // Update pointer into the buffer
    numbuffered = (numbuffered + numtopad) % s->spectra_per_subint;
    // Set the padding flag
    *padding = 1;
    // If we haven't gotten a full block, or completed the buffered one
    // then recursively call get_PSRFITS_rawblock()
    if (numbuffered) {
        printf("Adding %d spectra of padding to buffer at subint %d\n",
               numtopad, cur_subint);
        return get_PSRFITS_rawblock(fdata, s, padding);
    } else {
        printf("Adding %d spectra of padding at subint %d\n", numtopad, cur_subint);
        goto return_block;
    }

  return_block:
    // Apply the corrections that need a full block

    // Invert the band if needed
    if (s->apply_flipband)
        flip_band(fdata, s);

    // Perform Zero-DMing if requested
    if (s->remove_zerodm)
        remove_zerodm(fdata, s);

    // Increment our static counter (to determine how much data we
    // have written on the fly).
    cur_spec += s->spectra_per_subint;

    return 1;
}
Пример #17
0
 ~RelationMemberListBuilder() {
     add_padding();
 }
Пример #18
0
// flatten_operation: serialize a kssl_operation
kssl_error_code flatten_operation(kssl_header *header,
                                  kssl_operation *operation,
                                  BYTE **out_operation,
                                  int *length) {
    int local_req_len;
    BYTE *local_req;
    int offset = 0;
    if (header == NULL        ||
            operation == NULL     ||
            out_operation == NULL ||
            length == NULL) {
        return KSSL_ERROR_INTERNAL;
    }

    // Allocate response (header + opcode + response)
    local_req_len = KSSL_HEADER_SIZE;

    if (operation->is_opcode_set) {
        local_req_len += KSSL_OPCODE_ITEM_SIZE;
    }
    if (operation->is_payload_set) {
        local_req_len += KSSL_ITEM_HEADER_SIZE + operation->payload_len;
    }
    if (operation->is_digest_set) {
        local_req_len += KSSL_ITEM_HEADER_SIZE + KSSL_DIGEST_SIZE;
    }
    if (operation->is_ip_set) {
        local_req_len += KSSL_ITEM_HEADER_SIZE + operation->ip_len;
    }

    // The operation will always be padded to KSSL_PAD_TO +
    // KSSL_ITEM_HEADER_SIZE bytes

    int padding_size = 0;
    if (local_req_len < KSSL_PAD_TO) {
        padding_size = KSSL_PAD_TO - local_req_len;
    }

    local_req_len += KSSL_ITEM_HEADER_SIZE + padding_size;

    // The memory is calloced here to ensure that it is all zero. This is
    // important because the padding added below is done by just adding a
    // KSSL_ITEM at the end of the message stating that it has N bytes of
    // padding.

    local_req = (BYTE *)calloc(local_req_len, 1);
    if (local_req == NULL) {
        return KSSL_ERROR_INTERNAL;
    }

    // Override header length
    header->length = local_req_len - KSSL_HEADER_SIZE;

    flatten_header(header, local_req, &offset);
    if (operation->is_opcode_set) {
        flatten_item_byte(KSSL_TAG_OPCODE, operation->opcode, local_req, &offset);
    }
    if (operation->is_payload_set) {
        flatten_item(KSSL_TAG_PAYLOAD, operation->payload, operation->payload_len,
                     local_req, &offset);
    }
    if (operation->is_digest_set) {
        flatten_item(KSSL_TAG_DIGEST, operation->digest, KSSL_DIGEST_SIZE,
                     local_req, &offset);
    }
    if (operation->is_ip_set) {
        flatten_item(KSSL_TAG_CLIENT_IP, operation->ip, operation->ip_len,
                     local_req, &offset);
    }

    add_padding(padding_size, local_req, &offset);

    *out_operation = local_req;
    *length = local_req_len;

    return KSSL_ERROR_NONE;
}
Пример #19
0
static int sm_encrypt(const struct iso_sm_ctx *ctx, sc_card_t *card,
        const sc_apdu_t *apdu, sc_apdu_t **psm_apdu)
{
    struct sc_asn1_entry sm_capdu[4];
    u8 *p, *le = NULL, *sm_data = NULL, *fdata = NULL, *mac_data = NULL,
       *asn1 = NULL, *mac = NULL, *resp_data = NULL;
    size_t sm_data_len, fdata_len, mac_data_len, asn1_len, mac_len, le_len;
    int r, cse;
    sc_apdu_t *sm_apdu = NULL;

    if (!apdu || !ctx || !card || !card->reader || !psm_apdu) {
        r = SC_ERROR_INVALID_ARGUMENTS;
        goto err;
    }

    if ((apdu->cla & 0x0C) == 0x0C) {
        r = SC_ERROR_INVALID_ARGUMENTS;
        sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Given APDU is already protected with some secure messaging");
        goto err;
    }

    sc_copy_asn1_entry(c_sm_capdu, sm_capdu);

    sm_apdu = malloc(sizeof(sc_apdu_t));
    if (!sm_apdu) {
        r = SC_ERROR_OUT_OF_MEMORY;
        goto err;
    }
    sm_apdu->control = apdu->control;
    sm_apdu->flags = apdu->flags;
    sm_apdu->cla = apdu->cla|0x0C;
    sm_apdu->ins = apdu->ins;
    sm_apdu->p1 = apdu->p1;
    sm_apdu->p2 = apdu->p2;
    r = format_head(ctx, sm_apdu, &mac_data);
    if (r < 0) {
        sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not format header of SM apdu");
        goto err;
    }
    mac_data_len = r;

    /* get le and data depending on the case of the insecure command */
    cse = apdu->cse;
    if ((apdu->le/ctx->block_length + 1)*ctx->block_length + 18 > 0xff+1)
        /* for encrypted APDUs we usually get authenticated status bytes (4B),
         * a MAC (11B) and a cryptogram with padding indicator (3B without
         * data).  The cryptogram is always padded to the block size. */
        cse |= SC_APDU_EXT;

    switch (cse) {
        case SC_APDU_CASE_1:
            break;
	case SC_APDU_CASE_2_SHORT:
            le_len = 1;
            r = format_le(apdu->le, sm_capdu + 1, &le, &le_len);
            if (r < 0) {
                sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not format Le of SM apdu");
                goto err;
            }
            bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Protected Le (plain)", le, le_len);
            break;
	case SC_APDU_CASE_2_EXT:
            if (card->reader->active_protocol == SC_PROTO_T0) {
                /* T0 extended APDUs look just like short APDUs */
                le_len = 1;
                r = format_le(apdu->le, sm_capdu + 1, &le, &le_len);
                if (r < 0) {
                    sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not format Le of SM apdu");
                    goto err;
                }
            } else {
                /* in case of T1 always use 2 bytes for length */
                le_len = 2;
                r = format_le(apdu->le, sm_capdu + 1, &le, &le_len);
                if (r < 0) {
                    sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not format Le of SM apdu");
                    goto err;
                }
            }
            bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Protected Le (plain)", le, le_len);
            break;
        case SC_APDU_CASE_3_SHORT:
        case SC_APDU_CASE_3_EXT:
            r = format_data(card, ctx, apdu->data, apdu->datalen,
                    sm_capdu + 0, &fdata, &fdata_len);
            if (r < 0) {
                sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not format data of SM apdu");
                goto err;
            }
            bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Padding-content indicator followed by cryptogram (plain)",
                    fdata, fdata_len);
            break;
        case SC_APDU_CASE_4_SHORT:
            /* in case of T0 no Le byte is added */
            if (card->reader->active_protocol != SC_PROTO_T0) {
                le_len = 1;
                r = format_le(apdu->le, sm_capdu + 1, &le, &le_len);
                if (r < 0) {
                    sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not format Le of SM apdu");
                    goto err;
                }
                bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Protected Le (plain)", le, le_len);
            }

            r = format_data(card, ctx, apdu->data, apdu->datalen,
                    sm_capdu + 0, &fdata, &fdata_len);
            if (r < 0) {
                sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not format data of SM apdu");
                goto err;
            }
            bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Padding-content indicator followed by cryptogram (plain)",
                    fdata, fdata_len);
            break;
        case SC_APDU_CASE_4_EXT:
            if (card->reader->active_protocol == SC_PROTO_T0) {
                /* again a T0 extended case 4 APDU looks just
                 * like a short APDU, the additional data is
                 * transferred using ENVELOPE and GET RESPONSE */
            } else {
                /* only 2 bytes are use to specify the length of the
                 * expected data */
                le_len = 2;
                r = format_le(apdu->le, sm_capdu + 1, &le, &le_len);
                if (r < 0) {
                    sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not format Le of SM apdu");
                    goto err;
                }
                bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Protected Le (plain)", le, le_len);
            }

            r = format_data(card, ctx, apdu->data, apdu->datalen,
                    sm_capdu + 0, &fdata, &fdata_len);
            if (r < 0) {
                sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not format data of SM apdu");
                goto err;
            }
            bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Padding-content indicator followed by cryptogram (plain)",
                    fdata, fdata_len);
            break;
        default:
            sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Unhandled apdu case");
            r = SC_ERROR_INVALID_DATA;
            goto err;
    }


    r = sc_asn1_encode(card->ctx, sm_capdu, (u8 **) &asn1, &asn1_len);
    if (r < 0) {
        goto err;
    }
    if (asn1_len) {
        p = realloc(mac_data, mac_data_len + asn1_len);
        if (!p) {
            r = SC_ERROR_OUT_OF_MEMORY;
            goto err;
        }
        mac_data = p;
        /* Flawfinder: ignore */
        memcpy(mac_data + mac_data_len, asn1, asn1_len);
        mac_data_len += asn1_len;
        r = add_padding(ctx, mac_data, mac_data_len, &mac_data);
        if (r < 0) {
            goto err;
        }
        mac_data_len = r;
    }
    bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Data to authenticate", mac_data, mac_data_len);

    r = ctx->authenticate(card, ctx, mac_data, mac_data_len,
            &mac);
    if (r < 0) {
        sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not get authentication code");
        goto err;
    }
    mac_len = r;
    bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Cryptographic Checksum (plain)", mac, mac_len);


    /* format SM apdu */
    sc_format_asn1_entry(sm_capdu + 2, mac, &mac_len, SC_ASN1_PRESENT);
    r = sc_asn1_encode(card->ctx, sm_capdu, (u8 **) &sm_data, &sm_data_len);
    if (r < 0)
        goto err;
    sm_apdu->data = sm_data;
    sm_apdu->datalen = sm_data_len;
    sm_apdu->lc = sm_data_len;
    sm_apdu->le = 0;
    if (cse & SC_APDU_EXT) {
        sm_apdu->cse = SC_APDU_CASE_4_EXT;
#if OPENSC_NOT_BOGUS_ANYMORE
        sm_apdu->resplen = 0xffff+1;
#else
        sm_apdu->resplen = SC_MAX_EXT_APDU_BUFFER_SIZE;
#endif
    } else {
        sm_apdu->cse = SC_APDU_CASE_4_SHORT;
#if OPENSC_NOT_BOGUS_ANYMORE
        sm_apdu->resplen = 0xff+1;
#else
        sm_apdu->resplen = SC_MAX_APDU_BUFFER_SIZE;
#endif
    }
    resp_data = malloc(sm_apdu->resplen);
    if (!resp_data) {
        r = SC_ERROR_OUT_OF_MEMORY;
        goto err;
    }
    sm_apdu->resp = resp_data;
    bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "ASN.1 encoded encrypted APDU data", sm_apdu->data, sm_apdu->datalen);

    *psm_apdu = sm_apdu;

err:
    free(fdata);
    free(asn1);
    free(mac_data);
    free(mac);
    free(le);
    if (r < 0) {
        free(resp_data);
        free(sm_apdu);
        free(sm_data);
    }

    return r;
}
Пример #20
0
static int sm_decrypt(const struct iso_sm_ctx *ctx, sc_card_t *card,
        const sc_apdu_t *sm_apdu, sc_apdu_t *apdu)
{
    int r;
    struct sc_asn1_entry sm_rapdu[4];
    struct sc_asn1_entry my_sm_rapdu[4];
    u8 sw[2], mac[8], fdata[SC_MAX_EXT_APDU_BUFFER_SIZE];
    size_t sw_len = sizeof sw, mac_len = sizeof mac, fdata_len = sizeof fdata,
           buf_len, asn1_len;
    const u8 *buf;
    u8 *data = NULL, *mac_data = NULL, *asn1 = NULL;

    sc_copy_asn1_entry(c_sm_rapdu, sm_rapdu);
    sc_format_asn1_entry(sm_rapdu + 0, fdata, &fdata_len, 0);
    sc_format_asn1_entry(sm_rapdu + 1, sw, &sw_len, 0);
    sc_format_asn1_entry(sm_rapdu + 2, mac, &mac_len, 0);

    r = sc_asn1_decode(card->ctx, sm_rapdu, sm_apdu->resp, sm_apdu->resplen,
            &buf, &buf_len);
    if (r < 0)
        goto err;
    if (buf_len > 0) {
        r = SC_ERROR_UNKNOWN_DATA_RECEIVED;
        goto err;
    }


    if (sm_rapdu[2].flags & SC_ASN1_PRESENT) {
        /* copy from sm_apdu to my_sm_apdu, but leave mac at default */
        sc_copy_asn1_entry(sm_rapdu, my_sm_rapdu);
        sc_copy_asn1_entry(&c_sm_rapdu[2], &my_sm_rapdu[2]);

        r = sc_asn1_encode(card->ctx, my_sm_rapdu, &asn1, &asn1_len);
        if (r < 0)
            goto err;
        r = add_padding(ctx, asn1, asn1_len, &mac_data);
        if (r < 0) {
            goto err;
        }
        
        r = ctx->verify_authentication(card, ctx, mac, mac_len,
                mac_data, r);
        if (r < 0)
            goto err;
    } else {
        sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Cryptographic Checksum missing");
        r = SC_ERROR_ASN1_OBJECT_NOT_FOUND;
        goto err;
    }


    if (sm_rapdu[0].flags & SC_ASN1_PRESENT) {
        if (ctx->padding_indicator != fdata[0]) {
            r = SC_ERROR_UNKNOWN_DATA_RECEIVED;
            goto err;
        }
        r = ctx->decrypt(card, ctx, fdata + 1, fdata_len - 1, &data);
        if (r < 0)
            goto err;
        buf_len = r;

        r = rm_padding(ctx->padding_indicator, data, buf_len);
        if (r < 0) {
            sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not remove padding");
            goto err;
        }

        if (apdu->resplen < r || (r && !apdu->resp)) {
            sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,
                    "Response of SM APDU %u byte%s too long", r-apdu->resplen,
                    r-apdu->resplen < 2 ? "" : "s");
            r = SC_ERROR_OUT_OF_MEMORY;
            goto err;
        }
        /* Flawfinder: ignore */
        memcpy(apdu->resp, data, r);
        apdu->resplen = r;
    } else {
        apdu->resplen = 0;
    }

    if (sm_rapdu[1].flags & SC_ASN1_PRESENT) {
        if (sw_len != 2) {
            sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Length of processing status bytes must be 2");
            r = SC_ERROR_ASN1_END_OF_CONTENTS;
            goto err;
        }
        apdu->sw1 = sw[0];
        apdu->sw2 = sw[1];
    } else {
        sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Authenticated status bytes are missing");
        r = SC_ERROR_ASN1_OBJECT_NOT_FOUND;
        goto err;
    }

    sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Decrypted APDU sw1=%02x sw2=%02x",
            apdu->sw1, apdu->sw2);
    bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Decrypted APDU response data",
            apdu->resp, apdu->resplen);

    r = SC_SUCCESS;

err:
    free(asn1);
    free(mac_data);
    if (data) {
        sc_mem_clear(data, buf_len);
        free(data);
    }

    return r;
}
Пример #21
0
 ~TagListBuilder() {
     add_padding();
 }
Пример #22
0
 /**
  * Add user name to buffer.
  *
  * @param user Pointer to user name.
  * @param length Length of user name (without \0 termination).
  */
 void add_user(const char* user, const string_size_type length) {
     object().set_user_size(length + 1);
     add_size(append(user, length) + append_zero());
     add_padding(true);
 }
Пример #23
0
int get_PSRFITS_rawblock(float *fdata, struct spectra_info *s, int *padding)
// This routine reads a single block (i.e subint) from the input files
// which contain raw data in PSRFITS format.  If padding is
// returned as 1, then padding was added and statistics should not be
// calculated.  Return 1 on success.
{
    int numtopad = 0, numtoread, status = 0, anynull;
    float *fdataptr = fdata;
    double offs_sub;
    
    fdataptr = fdata + numbuffered * s->num_channels;
    // numtoread is always this size since we need to read
    // full PSRFITS subints...
    numtoread = s->spectra_per_subint;
    
    // If our buffer array is offset from last time, 
    // copy the previously offset part into the beginning.
    // New data comes after the old data in the buffer.
    if (numbuffered)
        memcpy(fdata, fdata + numtoread * s->num_channels, 
               numbuffered * s->num_channels * sizeof(float));
    
    // Make sure our current file number is valid
    if (cur_file >= s->num_files) return 0;
    
    // Read a subint of data from the DATA col
    if (cur_subint <= s->num_subint[cur_file]) {
        
        // Read the OFFS_SUB column value in case there were dropped blocks
        fits_read_col(s->fitsfiles[cur_file], TDOUBLE, 
                      s->offs_sub_col, cur_subint, 1L, 1L, 
                      0, &offs_sub, &anynull, &status);
        
        // Set last_offs_sub to proper value
        if (cur_subint==1 && (offs_sub < s->time_per_subint)) {
            if (cur_file==0) {
                // This is for the first time
                last_offs_sub = offs_sub - s->time_per_subint;
            } else {
                // And this is if we are combining observations
                last_offs_sub = (s->start_spec[cur_file] - 
                                 (cur_spec + numbuffered)) * s->dt - 
                    0.5 * s->time_per_subint;
            }
        }
        
        // The following determines if there were lost blocks.  We should
        // always be within 0.5 sample (and only that big if we are putting
        // two different observations together).
        if (fabs((offs_sub - last_offs_sub) - s->time_per_subint) < 0.5 * s->dt) {
            // if things look good, with no missing blocks, read the data
            get_PSRFITS_subint(fdataptr, cdatabuffer, s);
            last_offs_sub = offs_sub;
            cur_subint++;
            goto return_block;
        } else {
            if (offs_sub < last_offs_sub) { // Files out of order?  Shouldn't get here.
                fprintf(stderr, "Error!:  Current subint has earlier time than previous!\n\n"
                        "\tfilename = '%s', subint = %d\n"
                        "\tlast_offs_sub = %20.15f  offs_sub = %20.15f\n",
                        s->filenames[cur_file], cur_subint, last_offs_sub, offs_sub);
                exit(1);
            } else {  // there is some missing data, use padding
                numtopad = (int)round((offs_sub - last_offs_sub) / s->dt) - numbuffered;
                if (numtopad > s->spectra_per_subint) numtopad = s->spectra_per_subint;
                add_padding(fdataptr, s->padvals, s->num_channels, numtopad);
                // Update the time of the last subs based on this padding
                last_offs_sub += numtopad * s->dt;
                // Update pointer into the buffer
                numbuffered = (numbuffered + numtopad) % s->spectra_per_subint;
                // Set the padding flag
                *padding = 1;
                // If we haven't gotten a full block, or completed the buffered one
                // then recursively call get_PSRFITS_rawblock()
                if (numbuffered)
                    return get_PSRFITS_rawblock(fdata, s, padding);
                else
                    goto return_block;
            }
        }
        
    } else {
        // We can't read anymore...  so read OFFS_SUB for the last row
        // of the current file to see about padding
        fits_read_col(s->fitsfiles[cur_file], TDOUBLE, 
                      s->offs_sub_col, s->num_subint[cur_file], 1L, 1L, 
                      0, &offs_sub, &anynull, &status);
    }
    
    if (s->num_pad[cur_file]==0 ||
        (fabs(last_offs_sub - offs_sub) < 0.5 * s->dt)) {
        // No padding is necessary.  The second check means that the
        // lack of data we noticed upon reading the file was due to
        // dropped data in the middle of the file that we already
        // fixed.  So no padding is really necessary.
        cur_file++;
        cur_subint = 1;
        return get_PSRFITS_rawblock(fdata, s, padding);
    } else { // add padding
        // Set offs_sub to the correct offs_sub time for the first
        // row of the next file.  Since that might or might not
        // be from a different observation, use absolute times from
        // the start of the observation for both offs_sub and last_offs_sub
        offs_sub = s->start_spec[cur_file+1] * s->dt + 0.5 * s->time_per_subint;
        last_offs_sub = (cur_spec + numbuffered) * s->dt - 0.5 * s->time_per_subint;
        // Compute the amount of required padding
        numtopad = (int)round((offs_sub - last_offs_sub) / s->dt) - numbuffered;
        if (numtopad > s->spectra_per_subint) numtopad = s->spectra_per_subint;
        add_padding(fdataptr, s->padvals, s->num_channels, numtopad);
        // Update the time of the last subs based on this padding
        last_offs_sub += numtopad * s->dt;
        // Update pointer into the buffer
        numbuffered = (numbuffered + numtopad) % s->spectra_per_subint;
        // Set the padding flag
        *padding = 1;
        // If we haven't gotten a full block, or completed the buffered one
        // then recursively call get_PSRFITS_rawblock()
        if (numbuffered)
            return get_PSRFITS_rawblock(fdata, s, padding);
        else
            goto return_block;
    }
    
return_block:
    // Apply the corrections that need a full block

    // Invert the band if needed
    if (s->apply_flipband) flip_band(fdata, s);

    // Perform Zero-DMing if requested
    if (s->remove_zerodm) remove_zerodm(fdata, s);

    // Increment our static counter (to determine how much data we
    // have written on the fly).
    cur_spec += s->spectra_per_subint;

    return 1;
}
Пример #24
0
/*
 * Load program "progname" and start running it in usermode.
 * Does not return except on error.
 *
 * Calls vfs_open on progname and thus may destroy it.
 */
int
runprogram(char *progname, char **arguments, int argc)
{
    struct vnode *v;
    vaddr_t entrypoint, stackptr;
    int result;

    (void)arguments;

    /* Open the file. */
    result = vfs_open(progname, O_RDONLY, 0, &v);
    if (result) {
        return result;
    }

    /* We should be a new thread. */
    KASSERT(curthread->t_addrspace == NULL);

    /* Create a new address space. */
    curthread->t_addrspace = as_create();
    if (curthread->t_addrspace==NULL) {
        vfs_close(v);
        return ENOMEM;
    }

    /* Activate it. */
    as_activate(curthread->t_addrspace);


    /* Load the executable. */
    result = load_elf(v, &entrypoint);
    if (result) {
        /* thread_exit destroys curthread->t_addrspace */
        vfs_close(v);
        return result;
    }

    /* Done with the file now. */
    vfs_close(v);

    /* Define the user stack in the address space */
    result = as_define_stack(curthread->t_addrspace, &stackptr);
    if (result) {
        /* thread_exit destroys curthread->t_addrspace */
        return result;
    }

    char **argv;
    char *arg;
    int length, padding;

    //For each argument: Add padding, Decrement stackptr and copyout args
    for (int i=0; i<argc; i++) {
        length = strlen(arguments[i])+1;
        padding = 4-(length % 4);
        //Add padding
        arg = add_padding(arguments[i], padding);
        length = length+padding;
        //Decrement stackptr
        stackptr -= length;
        argv[i] = (char *)stackptr;
        //Copyout
        copyout(arg, (userptr_t) stackptr, length);
    }
    //Null terminate argv
    stackptr -= sizeof(char *)*(argc+1);
    argv[argc] = NULL;
    //Copyout argv
    copyout(argv, (userptr_t) stackptr, sizeof(char *)*(argc+1));

    /* Warp to user mode. */
    enter_new_process(argc, (userptr_t) stackptr, stackptr-1, entrypoint);

    /* enter_new_process does not return. */
    panic("enter_new_process returned\n");
    return EINVAL;
}