diff --git a/ChangeLog b/ChangeLog index 7bfa3e337fb4084770abbd626b81110c3693513b..548e2325630eb9219ed2b6c10be1062a1ffb7844 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2012-04-15 Niels Möller <nisse@lysator.liu.se> + + * testsuite/salsa20-test.c (test_salsa20_stream): New function. + (test_main): Tests for encrypting more than one block at a time. + 2012-04-14 Niels Möller <nisse@lysator.liu.se> * examples/io.c (write_file): Use write_string. diff --git a/testsuite/salsa20-test.c b/testsuite/salsa20-test.c index 57363f8ccd2604054b165f90504e716756309480..6be6d0453f858a2b7dd65818f1f2c5526343ccfd 100644 --- a/testsuite/salsa20-test.c +++ b/testsuite/salsa20-test.c @@ -1,6 +1,114 @@ #include "testutils.h" #include "salsa20.h" +#include "memxor.h" + +static int +memzero_p (const uint8_t *p, size_t n) +{ + size_t i; + for (i = 0; i < n; i++) + if (p[i]) + return 0; + return 1; +} + +/* The ecrypt testcases encrypt 512 zero bytes (8 blocks), then give + the xor of all blocks, and the data for block 0 (0-43), 3,4 + (192-319), 7 (448-511) */ + +#define STREAM_LENGTH 512 +static void +test_salsa20_stream(unsigned key_length, + const uint8_t *key, + const uint8_t *iv, + const uint8_t *ciphertext, + const uint8_t *xor_ref) +{ + struct salsa20_ctx ctx; + uint8_t data[STREAM_LENGTH + 1]; + uint8_t stream[STREAM_LENGTH]; + uint8_t xor[SALSA20_BLOCK_SIZE]; + unsigned j; + + salsa20_set_key(&ctx, key_length, key); + salsa20_set_iv(&ctx, iv); + memset(stream, 0, STREAM_LENGTH); + salsa20_crypt(&ctx, STREAM_LENGTH, stream, stream); + + if (!MEMEQ (64, stream, ciphertext)) + { + fprintf(stderr, "Error failed, offset 0:\n"); + fprintf(stderr, "\nOutput: "); + print_hex(64, stream); + fprintf(stderr, "\nExpected:"); + print_hex(64, ciphertext); + fprintf(stderr, "\n"); + FAIL(); + } + if (!MEMEQ (128, stream + 192, ciphertext + 64)) + { + fprintf(stderr, "Error failed, offset 192:\n"); + fprintf(stderr, "\nOutput: "); + print_hex(128, stream + 192); + fprintf(stderr, "\nExpected:"); + print_hex(64, ciphertext + 64); + fprintf(stderr, "\n"); + FAIL(); + } + if (!MEMEQ (64, stream + 448, ciphertext + 192)) + { + fprintf(stderr, "Error failed, offset 448:\n"); + fprintf(stderr, "\nOutput: "); + print_hex(64, stream + 448); + fprintf(stderr, "\nExpected:"); + print_hex(64, ciphertext + 192); + fprintf(stderr, "\n"); + FAIL(); + } + + memxor3 (xor, stream, stream + SALSA20_BLOCK_SIZE, SALSA20_BLOCK_SIZE); + for (j = 2*SALSA20_BLOCK_SIZE; j < STREAM_LENGTH; j += SALSA20_BLOCK_SIZE) + memxor (xor, stream + j, SALSA20_BLOCK_SIZE); + + if (!MEMEQ (SALSA20_BLOCK_SIZE, xor, xor_ref)) + { + fprintf(stderr, "Error failed, bad xor 448:\n"); + fprintf(stderr, "\nOutput: "); + print_hex(SALSA20_BLOCK_SIZE, xor); + fprintf(stderr, "\nExpected:"); + print_hex(SALSA20_BLOCK_SIZE, xor_ref); + fprintf(stderr, "\n"); + FAIL(); + } + + for (j = 1; j <= STREAM_LENGTH; j++) + { + memset(data, 0, STREAM_LENGTH + 1); + salsa20_set_iv(&ctx, iv); + salsa20_crypt(&ctx, j, data, data); + + if (!MEMEQ(j, data, stream)) + { + fprintf(stderr, "Encrypt failed for length %u:\n", j); + fprintf(stderr, "\nOutput: "); + print_hex(j, data); + fprintf(stderr, "\nExpected:"); + print_hex(j, stream); + fprintf(stderr, "\n"); + FAIL(); + } + if (!memzero_p (data + j, STREAM_LENGTH + 1 - j)) + { + fprintf(stderr, "Encrypt failed for length, %u wrote too much:\n", j); + fprintf(stderr, "\nOutput: "); + print_hex(STREAM_LENGTH + 1 - j, data + j); + fprintf(stderr, "\n"); + FAIL(); + } + } +} + static void test_salsa20(unsigned key_length, const uint8_t *key, @@ -84,5 +192,52 @@ test_main(void) HL("00000000 00000000"), H("F5FAD53F 79F9DF58")); + test_salsa20_stream(HL("80000000000000000000000000000000"), + H("00000000 00000000"), + H("4DFA5E481DA23EA09A31022050859936" + "DA52FCEE218005164F267CB65F5CFD7F" + "2B4F97E0FF16924A52DF269515110A07" + "F9E460BC65EF95DA58F740B7D1DBB0AA" + "DA9C1581F429E0A00F7D67E23B730676" + "783B262E8EB43A25F55FB90B3E753AEF" + "8C6713EC66C51881111593CCB3E8CB8F" + "8DE124080501EEEB389C4BCB6977CF95" + "7D5789631EB4554400E1E025935DFA7B" + "3E9039D61BDC58A8697D36815BF1985C" + "EFDF7AE112E5BB81E37ECF0616CE7147" + "FC08A93A367E08631F23C03B00A8DA2F" + "B375703739DACED4DD4059FD71C3C47F" + "C2F9939670FAD4A46066ADCC6A564578" + "3308B90FFB72BE04A6B147CBE38CC0C3" + "B9267C296A92A7C69873F9F263BE9703"), + H("F7A274D268316790A67EC058F45C0F2A" + "067A99FCDE6236C0CEF8E056349FE54C" + "5F13AC74D2539570FD34FEAB06C57205" + "3949B59585742181A5A760223AFA22D4")); + + test_salsa20_stream(HL("48494A4B4C4D4E4F5051525354555657" + "58595A5B5C5D5E5F6061626364656667"), + H("0000000000000000"), + H("53AD3698A011F779AD71030F3EFBEBA0" + "A7EE3C55789681B1591EF33A7BE521ED" + "68FC36E58F53FFD6E1369B00E390E973" + "F656ACB097E0D603BE59A0B8F7975B98" + "A04698274C6AC6EC03F66ED3F94C08B7" + "9FFDBF2A1610E6F5814905E73AD6D0D2" + "8164EEB8450D8ED0BB4B644761B43512" + "52DD5DDF00C31E3DABA0BC17691CCFDC" + "B826C7F071E796D34E3BFFB3C96E76A1" + "209388392806947C7F19B86D379FA3AE" + "DFCD19EBF49803DACC6E577E5B97B0F6" + "D2036B6624D8196C96FCF02C865D30C1" + "B505D41E2C207FA1C0A0E93413DDCFFC" + "9BECA8030AFFAC2466E56482DA0EF428" + "E63880B5021D3051F18679505A2B9D4F" + "9B2C5A2D271D276DE3F51DBEBA934436"), + H("7849651A820B1CDFE36D5D6632716534" + "E0635EDEFD538122D80870B60FB055DB" + "637C7CA2B78B116F83AFF46E40F8F71D" + "4CD6D2E1B750D5E011D1DF2E80F7210A")); + SUCCESS(); }