Verify DM media record boundaries and corrupted artifacts
This commit is contained in:
1 parent
467d2e7605
commit
bd05ab6d3a
1 file changed
+82
@@ -15,6 +15,85 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "../lib/mem.h"
|
#include "../lib/mem.h"
|
||||||
|
|
||||||
|
/* Потоковые файлы разного размера; результат доступен только после всех проверок. */
|
||||||
|
static int test_media_stream(const uint8_t key1[32], const uint8_t key2[32], uint64_t author, size_t size) {
|
||||||
|
FILE* src = tmpfile();
|
||||||
|
FILE* cipher = tmpfile();
|
||||||
|
FILE* plain = tmpfile();
|
||||||
|
FILE* short_cipher = tmpfile();
|
||||||
|
if (!src || !cipher || !plain || !short_cipher) {
|
||||||
|
DEBUG_ERROR(DEBUG_CATEGORY_DM, "media test temporary file creation failed");
|
||||||
|
if (src) fclose(src);
|
||||||
|
if (cipher) fclose(cipher);
|
||||||
|
if (plain) fclose(plain);
|
||||||
|
if (short_cipher) fclose(short_cipher);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
uint8_t pattern[4096], actual[4096], id[16] = {1}, hash[32];
|
||||||
|
for (size_t i = 0; i < sizeof(pattern); i++) pattern[i] = (uint8_t)(i * 17 + 3);
|
||||||
|
int failed = 0;
|
||||||
|
size_t remaining = size;
|
||||||
|
while (remaining) {
|
||||||
|
size_t n = remaining > sizeof(pattern) ? sizeof(pattern) : remaining;
|
||||||
|
if (fwrite(pattern, 1, n, src) != n) { failed = 1; goto done; }
|
||||||
|
remaining -= n;
|
||||||
|
}
|
||||||
|
rewind(src);
|
||||||
|
uint64_t reported_size = 0;
|
||||||
|
if (dm_media_encrypt_stream(key1, author, id, src, cipher, &reported_size, hash) != 0 || reported_size != size) {
|
||||||
|
failed = 1;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
long cipher_size = ftell(cipher);
|
||||||
|
size_t records = size ? (size + DM_MEDIA_PLAIN_SIZE - 1) / DM_MEDIA_PLAIN_SIZE : 1;
|
||||||
|
if (cipher_size != (long)(size + records * DM_TAG_SIZE)) { failed = 1; goto done; }
|
||||||
|
rewind(cipher);
|
||||||
|
if (dm_media_decrypt_stream(key2, author, id, size, hash, cipher, plain) != 0 || ftell(plain) != (long)size) {
|
||||||
|
failed = 1;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
rewind(plain);
|
||||||
|
remaining = size;
|
||||||
|
while (remaining) {
|
||||||
|
size_t n = remaining > sizeof(actual) ? sizeof(actual) : remaining;
|
||||||
|
if (fread(actual, 1, n, plain) != n || memcmp(actual, pattern, n)) { failed = 1; goto done; }
|
||||||
|
remaining -= n;
|
||||||
|
}
|
||||||
|
/* Неправильный получатель, автор, ID и manifest hash не принимаются. */
|
||||||
|
uint8_t wrong_key[32] = {0};
|
||||||
|
rewind(cipher);
|
||||||
|
if (dm_media_decrypt_stream(wrong_key, author, id, size, hash, cipher, plain) == 0) failed = 1;
|
||||||
|
rewind(cipher);
|
||||||
|
if (dm_media_decrypt_stream(key2, author + 1, id, size, hash, cipher, plain) == 0) failed = 1;
|
||||||
|
id[1] = 1;
|
||||||
|
rewind(cipher);
|
||||||
|
if (dm_media_decrypt_stream(key2, author, id, size, hash, cipher, plain) == 0) failed = 1;
|
||||||
|
id[1] = 0;
|
||||||
|
hash[0] ^= 1;
|
||||||
|
rewind(cipher);
|
||||||
|
if (dm_media_decrypt_stream(key2, author, id, size, hash, cipher, plain) == 0) failed = 1;
|
||||||
|
hash[0] ^= 1;
|
||||||
|
/* Обрезанный файл и лишние байты обнаруживаются независимо от тегов порций. */
|
||||||
|
rewind(cipher);
|
||||||
|
for (long i = 0; i < cipher_size - 1; i++) {
|
||||||
|
int ch = fgetc(cipher);
|
||||||
|
if (ch == EOF || fputc(ch, short_cipher) == EOF) { failed = 1; goto done; }
|
||||||
|
}
|
||||||
|
rewind(short_cipher);
|
||||||
|
if (dm_media_decrypt_stream(key2, author, id, size, hash, short_cipher, plain) == 0) failed = 1;
|
||||||
|
fseek(cipher, 0, SEEK_END);
|
||||||
|
if (fputc(1, cipher) == EOF) { failed = 1; goto done; }
|
||||||
|
rewind(cipher);
|
||||||
|
if (dm_media_decrypt_stream(key2, author, id, size, hash, cipher, plain) == 0) failed = 1;
|
||||||
|
done:
|
||||||
|
fclose(src);
|
||||||
|
fclose(cipher);
|
||||||
|
fclose(plain);
|
||||||
|
fclose(short_cipher);
|
||||||
|
if (failed) DEBUG_ERROR(DEBUG_CATEGORY_DM, "media stream test failed plain_size=%zu", size);
|
||||||
|
return failed;
|
||||||
|
}
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
debug_config_init();
|
debug_config_init();
|
||||||
debug_set_level(DEBUG_LEVEL_ERROR);
|
debug_set_level(DEBUG_LEVEL_ERROR);
|
||||||
@@ -131,6 +210,9 @@ int main(void) {
|
|||||||
u_free(large);
|
u_free(large);
|
||||||
u_free(cipher);
|
u_free(cipher);
|
||||||
u_free(restored);
|
u_free(restored);
|
||||||
|
const size_t file_sizes[] = {0, 1, DM_MEDIA_PLAIN_SIZE, DM_MEDIA_PLAIN_SIZE + 1, DM_MEDIA_PLAIN_SIZE * 3 + 77};
|
||||||
|
for (size_t i = 0; i < sizeof(file_sizes) / sizeof(file_sizes[0]); i++)
|
||||||
|
failures += test_media_stream(key1, key2, a, file_sizes[i]);
|
||||||
|
|
||||||
if (failures == 0) {
|
if (failures == 0) {
|
||||||
printf("TEST PASSED\n");
|
printf("TEST PASSED\n");
|
||||||
|
|||||||
Reference in new issue
Block a user