Beispiel #1
0
static void mega_aes_key_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
{
    MegaAesKey *aes_key = MEGA_AES_KEY(object);

    switch (property_id)
    {
    default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
    }
}
/**
 * mega_aes_ctr_encryptor_set_mac:
 * @aes_ctr_encryptor: a #MegaAesCtrEncryptor
 * @mac: a #MegaChunkedCbcMac calculator
 *
 * Add calculator for mac's.
 */
void mega_aes_ctr_encryptor_set_mac(MegaAesCtrEncryptor* aes_ctr_encryptor, MegaChunkedCbcMac* mac, MegaAesCtrEncryptorDirection dir)
{
  MegaAesCtrEncryptorPrivate* priv;
  guchar mac_iv[16];

  g_return_if_fail(MEGA_IS_AES_CTR_ENCRYPTOR(aes_ctr_encryptor));
  g_return_if_fail(MEGA_IS_CHUNKED_CBC_MAC(mac));
  g_return_if_fail(aes_ctr_encryptor->priv->key != NULL);

  priv = aes_ctr_encryptor->priv;
  priv->direction = dir;

  g_clear_object(&priv->mac);
  priv->mac = g_object_ref(mac);

  // mac iv is nonce + nonce

  mega_file_key_get_nonce(priv->key, mac_iv);
  mega_file_key_get_nonce(priv->key, mac_iv + 8);

  mega_chunked_cbc_mac_setup(mac, MEGA_AES_KEY(priv->key), mac_iv);
}
static GConverterResult convert(GConverter *converter, const void *inbuf, gsize inbuf_size, void *outbuf, gsize outbuf_size, GConverterFlags flags, gsize *bytes_read, gsize *bytes_written, GError **error)
{
  MegaAesCtrEncryptor *encryptor = MEGA_AES_CTR_ENCRYPTOR(converter);
  MegaAesCtrEncryptorPrivate* priv = encryptor->priv;
  guchar nonce[8];

  if (!priv->key || !mega_aes_key_is_loaded(MEGA_AES_KEY(priv->key)))
  {
    g_set_error(error, 1, 0, "No key is set for AES-CTR decryption/encryption!");
    return G_CONVERTER_ERROR;
  }

  if (outbuf_size < inbuf_size) 
  {
    g_set_error(error, G_IO_ERROR, G_IO_ERROR_NO_SPACE, "No space");
    return G_CONVERTER_ERROR;
  }

  *bytes_written = *bytes_read = 0;
  mega_file_key_get_nonce(priv->key, nonce);

  // if input is not aligned, align it
  if (inbuf_size > 0 && priv->position % 16 != 0)
  {
    gsize offset = priv->position % 16;;
    gsize to_align = MIN(inbuf_size, 16 - offset);
    guchar align_buf[16];

    if (priv->direction == MEGA_AES_CTR_ENCRYPTOR_DIRECTION_ENCRYPT && priv->mac)
      mega_chunked_cbc_mac_update(priv->mac, align_buf + offset, to_align);

    memcpy(align_buf + offset, inbuf, to_align);
    mega_aes_key_encrypt_ctr(MEGA_AES_KEY(priv->key), nonce, priv->position / 16, align_buf, align_buf, 16);
    memcpy(outbuf, align_buf + offset, to_align);

    if (priv->direction == MEGA_AES_CTR_ENCRYPTOR_DIRECTION_DECRYPT)
      mega_chunked_cbc_mac_update(priv->mac, outbuf, to_align);

    *bytes_written = *bytes_read = to_align;
    priv->position += to_align;
    outbuf += to_align; inbuf += to_align;
    inbuf_size -= to_align; outbuf_size -= to_align;
  }

  // we are aligned, and there are more data on the input
  if (inbuf_size > 0)
  {
    if (priv->direction == MEGA_AES_CTR_ENCRYPTOR_DIRECTION_ENCRYPT && priv->mac)
      mega_chunked_cbc_mac_update(priv->mac, inbuf, inbuf_size);

    mega_aes_key_encrypt_ctr(MEGA_AES_KEY(priv->key), nonce, priv->position / 16, inbuf, outbuf, inbuf_size);

    if (priv->direction == MEGA_AES_CTR_ENCRYPTOR_DIRECTION_DECRYPT && priv->mac)
      mega_chunked_cbc_mac_update(priv->mac, outbuf, inbuf_size);

    *bytes_written = *bytes_read = *bytes_read + inbuf_size;
    priv->position += inbuf_size;
  }

  if (flags & G_CONVERTER_INPUT_AT_END)
    return G_CONVERTER_FINISHED;

  if (flags & G_CONVERTER_FLUSH)
    return G_CONVERTER_FLUSHED;

  return G_CONVERTER_CONVERTED;
}