Skip to content

SPECK64 different output if input is passed in chunks #945

@guidovranken

Description

@guidovranken

Reproducer:

#include <modes.h>
#include <filters.h>
#include <speck.h>

#define CF_CHECK_EQ(expr, res) if ( (expr) != (res) ) { goto end; }

std::vector<uint8_t> Encrypt(const std::vector<uint8_t>& key, const std::vector<uint8_t>& iv, const std::vector<std::vector<uint8_t>>& cleartext) {
    ::CryptoPP::OFB_Mode<::CryptoPP::SPECK64>::Encryption enc(key.data(), key.size(), iv.data());
    ::CryptoPP::StreamTransformationFilter encryptor(enc, nullptr);
    for (const auto& part : cleartext) {
        encryptor.Put(part.data(), part.size());
    }
    encryptor.MessageEnd();
    std::vector<uint8_t> out(encryptor.MaxRetrievable());
    encryptor.Get(out.data(), out.size());
    return out;
}

std::vector<uint8_t> Decrypt(const std::vector<uint8_t>& key, const std::vector<uint8_t>& iv, const std::vector<uint8_t>& ciphertext) {
    ::CryptoPP::OFB_Mode<::CryptoPP::SPECK64>::Decryption dec(key.data(), key.size(), iv.data());
    ::CryptoPP::StreamTransformationFilter decryptor(dec, nullptr);
    decryptor.Put(ciphertext.data(), ciphertext.size());
    decryptor.MessageEnd();
    std::vector<uint8_t> out(decryptor.MaxRetrievable());
    decryptor.Get(out.data(), out.size());
    return out;
}

int main(void)
{
    const std::vector<std::vector<uint8_t>> cleartext{
#if !defined(CHUNKED)
        {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
#else
        {0x00},
              {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
                                                              {0x00, 0x00, 0x00, 0x00, 0x00},
                                                                                            {0x00},
                                                                                                  {0x00},
#endif
    };
    const std::vector<uint8_t> key(16);
    const std::vector<uint8_t> iv(8);
    const auto ciphertext = Encrypt(key, iv, cleartext);

    const auto cleartext2 = Decrypt(key, iv, ciphertext);

    for (size_t i = 0; i < cleartext2.size(); i++) {
        printf("%02X ", cleartext2[i]);
    }
    printf("\n");
end:
    return 0;
}

Compile this with and without -DCHUNKED. Both should output:

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

But when compiled with -DCHUNKED, it outputs:

00 00 00 00 00 00 00 00 BD DD D9 80 6A 84 CF 2A

Tested on Linux x64, Crypto++ recent master branch.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions