54 lines
3.4 KiB
C
54 lines
3.4 KiB
C
/* Проверка контейнера на границах порций, подмены metadata/header, неверного ключа
|
|
* и отсутствия публикации частичного plaintext после любого отказа. */
|
|
#include "../src/media_async/encrypted_file.h"
|
|
#include "../src/media_async/media_async.h"
|
|
#include "../lib/debug_config.h"
|
|
#include "test_utils.h"
|
|
#include <assert.h>
|
|
#include <openssl/rand.h>
|
|
|
|
static void roundtrip(const char* dir, unsigned size) {
|
|
char source[768], cipher[768], output[768];
|
|
snprintf(source, sizeof(source), "%s/source", dir); snprintf(cipher, sizeof(cipher), "%s/cipher", dir);
|
|
snprintf(output, sizeof(output), "%s/output", dir);
|
|
FILE* f = fopen(source, "wb"); assert(f);
|
|
for (unsigned i = 0; i < size; i++) assert(fputc((i * 73 + 19) & 255, f) != EOF);
|
|
assert(!fclose(f));
|
|
uint8_t key[32], wrong[32], id[16], hash[32];
|
|
assert(RAND_bytes(key, 32) == 1 && RAND_bytes(wrong, 32) == 1 && RAND_bytes(id, 16) == 1);
|
|
struct attachment_info info = { .kind = ATTACHMENT_FILE, .name = "секретный-документ.bin" }, result;
|
|
char type[32];
|
|
assert(!encrypted_file_write(source, cipher, key, 42, id, &info, "application/octet-stream"));
|
|
assert(!ma_sha256_file(cipher, hash));
|
|
assert(!encrypted_file_read(cipher, output, key, 42, id, hash, &result, type));
|
|
assert(!strcmp(info.name, result.name) && !strcmp(type, "application/octet-stream"));
|
|
f = fopen(output, "rb"); assert(f);
|
|
for (unsigned i = 0; i < size; i++) assert(fgetc(f) == (int)((i * 73 + 19) & 255));
|
|
assert(fgetc(f) == EOF); assert(!fclose(f)); assert(!remove(output));
|
|
assert(encrypted_file_read(cipher, output, wrong, 42, id, hash, &result, type) < 0);
|
|
assert(ma_file_size(output) < 0);
|
|
assert(encrypted_file_read(cipher, output, key, 43, id, hash, &result, type) < 0);
|
|
id[0] ^= 1;
|
|
assert(encrypted_file_read(cipher, output, key, 42, id, hash, &result, type) < 0); id[0] ^= 1;
|
|
/* Подмена metadata даже с заново вычисленным внешним hash не проходит CCM. */
|
|
f = fopen(cipher, "rb+"); assert(f && !fseek(f, 70, SEEK_SET));
|
|
int c = fgetc(f); assert(c != EOF && !fseek(f, 70, SEEK_SET) && fputc(c ^ 1, f) != EOF && !fclose(f));
|
|
assert(encrypted_file_read(cipher, output, key, 42, id, hash, &result, type) < 0);
|
|
assert(!ma_sha256_file(cipher, hash));
|
|
assert(encrypted_file_read(cipher, output, key, 42, id, hash, &result, type) < 0 && ma_file_size(output) < 0);
|
|
assert(!encrypted_file_write(source, cipher, key, 42, id, &info, "application/octet-stream"));
|
|
/* Обрезанный контейнер и лишние байты отвергаются независимо от manifest hash. */
|
|
f = fopen(cipher, "ab"); assert(f && fputc(0, f) != EOF && !fclose(f));
|
|
assert(!ma_sha256_file(cipher, hash));
|
|
assert(encrypted_file_read(cipher, output, key, 42, id, hash, &result, type) < 0 && ma_file_size(output) < 0);
|
|
printf("PASS: encrypted container size=%u, metadata, identity, key and integrity checks\n", size);
|
|
}
|
|
|
|
int main(void) {
|
|
debug_config_init(); debug_set_level(DEBUG_LEVEL_ERROR);
|
|
char dir[512] = "/tmp/utun_encrypted_file_XXXXXX"; assert(!test_mkdtemp(dir));
|
|
const unsigned sizes[] = { 0, 1, 32767, 32768, 32769, 98321 };
|
|
for (unsigned i = 0; i < sizeof(sizes) / sizeof(sizes[0]); i++) roundtrip(dir, sizes[i]);
|
|
return 0;
|
|
}
|