Exemple #1
0
bool Core::loadEncryptedSave(QByteArray& data)
{
    if (!Settings::getInstance().getEncryptTox())
        GUI::showWarning(tr("Encryption error"), tr("The .tox file is encrypted, but encryption was not checked, continuing regardless."));

    size_t fileSize = data.size();
    int error = -1;
    QString a(tr("Please enter the password for the %1 profile.", "used in load() when no pw is already set").arg(Settings::getInstance().getCurrentProfile()));
    QString b(tr("The previous password is incorrect; please try again:", "used on retries in load()"));
    QString dialogtxt;

    if (pwsaltedkeys[ptMain]) // password set, try it
    {
        QByteArray newData(fileSize-TOX_PASS_ENCRYPTION_EXTRA_LENGTH, 0);
        if (tox_pass_key_decrypt((uint8_t*)data.data(), fileSize, pwsaltedkeys[ptMain],
                                 (uint8_t*)newData.data(), nullptr))
        {
            data = newData;
            Settings::getInstance().setEncryptTox(true);
            return true;
        }

        dialogtxt = tr("The profile password failed. Please try another?", "used only when pw set before load() doesn't work");
    }
    else
    {
        dialogtxt = a;
    }

    uint8_t salt[TOX_PASS_SALT_LENGTH];
    tox_get_salt(reinterpret_cast<uint8_t *>(data.data()), salt);

    do
    {
        QString pw = GUI::passwordDialog(tr("Change profile"), dialogtxt);

        if (pw.isEmpty())
        {
            clearPassword(ptMain);
            return false;
        }
        else
        {
            setPassword(pw, ptMain, salt);
        }

        QByteArray newData(fileSize-TOX_PASS_ENCRYPTION_EXTRA_LENGTH, 0);
        error = !tox_pass_key_decrypt((uint8_t*)data.data(), data.size(), pwsaltedkeys[ptMain],
                                 (uint8_t*)newData.data(), nullptr);
        if (!error)
            data = newData;

        dialogtxt = a + "\n" + b;
    } while (error != 0);

    Settings::getInstance().setEncryptTox(true);
    return true;
}
Exemple #2
0
/* Decrypts the given data with the given passphrase. The output array must be
 * at least data_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. This delegates
 * to tox_pass_key_decrypt.
 *
 * the output data has size data_length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH
 *
 * returns true on success
 */
bool tox_pass_decrypt(const uint8_t *data, size_t length, const uint8_t *passphrase, size_t pplength, uint8_t *out,
                      TOX_ERR_DECRYPTION *error)
{
    if (length <= TOX_PASS_ENCRYPTION_EXTRA_LENGTH) {
        SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_INVALID_LENGTH);
        return 0;
    }

    if (!data || !passphrase || !out) {
        SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_NULL);
        return 0;
    }

    if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) != 0) {
        SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_BAD_FORMAT);
        return 0;
    }

    uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES];
    memcpy(salt, data + TOX_ENC_SAVE_MAGIC_LENGTH, crypto_pwhash_scryptsalsa208sha256_SALTBYTES);

    /* derive the key */
    Tox_Pass_Key key;

    if (!tox_pass_key_derive_with_salt(&key, passphrase, pplength, salt, NULL)) {
        /* out of memory most likely */
        SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_KEY_DERIVATION_FAILED);
        return 0;
    }

    return tox_pass_key_decrypt(&key, data, length, out, error);
}
Exemple #3
0
QByteArray Core::decryptData(const QByteArray& data, PasswordType passtype)
{
    if (!pwsaltedkeys[passtype])
        return QByteArray();

    int sz = data.size() - TOX_PASS_ENCRYPTION_EXTRA_LENGTH;
    uint8_t decrypted[sz];
    if (!tox_pass_key_decrypt(reinterpret_cast<const uint8_t*>(data.data()), data.size(),
                              pwsaltedkeys[passtype], decrypted, nullptr))
    {
        qWarning() << "decryptData: decryption failed";
        return QByteArray();
    }
    return QByteArray(reinterpret_cast<char*>(decrypted), sz);
}
Exemple #4
0
QByteArray Core::decryptData(const QByteArray& data, const Tox_Pass_Key& encryptionKey)
{
    if (data.size() < TOX_PASS_ENCRYPTION_EXTRA_LENGTH)
    {
        qWarning() << "Not enough data:" << data.size();
        return QByteArray();
    }
    int decryptedSize = data.size() - TOX_PASS_ENCRYPTION_EXTRA_LENGTH;
    QByteArray decrypted(decryptedSize, 0x00);
    if (!tox_pass_key_decrypt(&encryptionKey, reinterpret_cast<const uint8_t*>(data.data()), data.size(),
                              (uint8_t*) decrypted.data(), nullptr))
    {
        qWarning() << "Decryption failed";
        return QByteArray();
    }
    return decrypted;
}
Exemple #5
0
END_TEST

START_TEST(test_keys)
{
    TOX_ERR_ENCRYPTION encerr;
    TOX_ERR_DECRYPTION decerr;
    TOX_ERR_KEY_DERIVATION keyerr;
    TOX_PASS_KEY key;
    bool ret = tox_derive_key_from_pass("123qweasdzxc", 12, &key, &keyerr);
    ck_assert_msg(ret, "generic failure 1: %u", keyerr);
    uint8_t *string = "No Patrick, mayonnaise is not an instrument."; // 44

    uint8_t encrypted[44 + TOX_PASS_ENCRYPTION_EXTRA_LENGTH];
    ret = tox_pass_key_encrypt(string, 44, &key, encrypted, &encerr);
    ck_assert_msg(ret, "generic failure 2: %u", encerr);

    uint8_t encrypted2[44 + TOX_PASS_ENCRYPTION_EXTRA_LENGTH];
    ret = tox_pass_encrypt(string, 44, "123qweasdzxc", 12, encrypted2, &encerr);
    ck_assert_msg(ret, "generic failure 3: %u", encerr);

    uint8_t out1[44 + TOX_PASS_ENCRYPTION_EXTRA_LENGTH];
    uint8_t out2[44 + TOX_PASS_ENCRYPTION_EXTRA_LENGTH];

    ret = tox_pass_key_decrypt(encrypted, 44 + TOX_PASS_ENCRYPTION_EXTRA_LENGTH, &key, out1, &decerr);
    ck_assert_msg(ret, "generic failure 4: %u", decerr);
    ck_assert_msg(memcmp(out1, string, 44) == 0, "decryption 1 failed");

    ret = tox_pass_decrypt(encrypted2, 44 + TOX_PASS_ENCRYPTION_EXTRA_LENGTH, "123qweasdzxc", 12, out2, &decerr);
    ck_assert_msg(ret, "generic failure 5: %u", decerr);
    ck_assert_msg(memcmp(out2, string, 44) == 0, "decryption 2 failed");

    // test that pass_decrypt can decrypt things from pass_key_encrypt
    ret = tox_pass_decrypt(encrypted, 44 + TOX_PASS_ENCRYPTION_EXTRA_LENGTH, "123qweasdzxc", 12, out1, &decerr);
    ck_assert_msg(ret, "generic failure 6: %u", decerr);
    ck_assert_msg(memcmp(out1, string, 44) == 0, "decryption 3 failed");

    uint8_t salt[TOX_PASS_SALT_LENGTH];
    ck_assert_msg(tox_get_salt(encrypted, salt), "couldn't get salt");
    TOX_PASS_KEY key2;
    ret = tox_derive_key_with_salt("123qweasdzxc", 12, salt, &key2, &keyerr);
    ck_assert_msg(ret, "generic failure 7: %u", keyerr);
    ck_assert_msg(0 == memcmp(&key, &key2, sizeof(TOX_PASS_KEY)), "salt comparison failed");
}
Exemple #6
0
END_TEST

START_TEST(test_save_friend)
{
    Tox *tox1 = tox_new(0, 0);
    Tox *tox2 = tox_new(0, 0);
    ck_assert_msg(tox1 || tox2, "Failed to create 2 tox instances");
    uint32_t to_compare = 974536;
    tox_callback_friend_request(tox2, accept_friend_request, &to_compare);
    uint8_t address[TOX_ADDRESS_SIZE];
    tox_self_get_address(tox2, address);
    uint32_t test = tox_friend_add(tox1, address, (uint8_t *)"Gentoo", 7, 0);
    ck_assert_msg(test != UINT32_MAX, "Failed to add friend");

    size_t size = tox_get_savedata_size(tox1);
    uint8_t data[size];
    tox_get_savedata(tox1, data);
    size_t size2 = size + TOX_PASS_ENCRYPTION_EXTRA_LENGTH;
    uint8_t enc_data[size2];
    TOX_ERR_ENCRYPTION error1;
    bool ret = tox_pass_encrypt(data, size, "correcthorsebatterystaple", 25, enc_data, &error1);
    ck_assert_msg(ret, "failed to encrypted save: %u", error1);
    ck_assert_msg(tox_is_data_encrypted(enc_data), "magic number missing");

    struct Tox_Options options;
    tox_options_default(&options);
    options.savedata_type = TOX_SAVEDATA_TYPE_TOX_SAVE;
    options.savedata_data = enc_data;
    options.savedata_length = size2;

    TOX_ERR_NEW err2;
    Tox *tox3 = tox_new(&options, &err2);
    ck_assert_msg(err2 == TOX_ERR_NEW_LOAD_ENCRYPTED, "wrong error! %u. should fail with %u", err2,
                  TOX_ERR_NEW_LOAD_ENCRYPTED);
    uint8_t dec_data[size];
    TOX_ERR_DECRYPTION err3;
    ret = tox_pass_decrypt(enc_data, size2, "correcthorsebatterystaple", 25, dec_data, &err3);
    ck_assert_msg(ret, "failed to decrypt save: %u", err3);
    options.savedata_data = dec_data;
    options.savedata_length = size;
    tox3 = tox_new(&options, &err2);
    ck_assert_msg(err2 == TOX_ERR_NEW_OK, "failed to load from decrypted data: %u", err2);
    uint8_t address2[TOX_PUBLIC_KEY_SIZE];
    ret = tox_friend_get_public_key(tox3, 0, address2, 0);
    ck_assert_msg(ret, "no friends!");
    ck_assert_msg(memcmp(address, address2, TOX_PUBLIC_KEY_SIZE) == 0, "addresses don't match!");

    size = tox_get_savedata_size(tox3);
    uint8_t data2[size];
    tox_get_savedata(tox3, data2);
    TOX_PASS_KEY key;
    memcpy(key.salt, salt, 32);
    memcpy(key.key, known_key2, crypto_box_BEFORENMBYTES);
    size2 = size + TOX_PASS_ENCRYPTION_EXTRA_LENGTH;
    uint8_t encdata2[size2];
    ret = tox_pass_key_encrypt(data2, size, &key, encdata2, &error1);
    ck_assert_msg(ret, "failed to key encrypt %u", error1);
    ck_assert_msg(tox_is_data_encrypted(encdata2), "magic number the second missing");

    uint8_t out1[size], out2[size];
    ret = tox_pass_decrypt(encdata2, size2, pw, pwlen, out1, &err3);
    ck_assert_msg(ret, "failed to pw decrypt %u", err3);
    ret = tox_pass_key_decrypt(encdata2, size2, &key, out2, &err3);
    ck_assert_msg(ret, "failed to key decrypt %u", err3);
    ck_assert_msg(memcmp(out1, out2, size) == 0, "differing output data");

    // and now with the code in use (I only bothered with manually to debug this, and it seems a waste
    // to remove the manual check now that it's there)
    options.savedata_data = out1;
    options.savedata_length = size;
    Tox *tox4 = tox_new(&options, &err2);
    ck_assert_msg(err2 == TOX_ERR_NEW_OK, "failed to new the third");
    uint8_t address5[TOX_PUBLIC_KEY_SIZE];
    ret = tox_friend_get_public_key(tox4, 0, address5, 0);
    ck_assert_msg(ret, "no friends! the third");
    ck_assert_msg(memcmp(address, address2, TOX_PUBLIC_KEY_SIZE) == 0, "addresses don't match! the third");

    tox_kill(tox1);
    tox_kill(tox2);
    tox_kill(tox3);
    tox_kill(tox4);
}