LCOV - code coverage report
Current view: top level - tests/unit - test_ige_aes.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 100.0 % 69 69
Test Date: 2026-04-20 19:54:22 Functions: 100.0 % 9 9

            Line data    Source code
       1              : /**
       2              :  * @file test_ige_aes.c
       3              :  * @brief Unit tests for AES-256-IGE (using mock crypto).
       4              :  *
       5              :  * Verifies IGE block chaining logic and call counts with mock crypto.
       6              :  * Real-crypto functional tests (known-answer, IV propagation) belong in
       7              :  * a separate functional test binary linked with production crypto.c.
       8              :  *
       9              :  * Known mock limitations (functional tests needed):
      10              :  *   - Mock encrypt_block is identity → identical plaintext blocks may produce
      11              :  *     identical ciphertext (IV XOR cancellation when iv_c == iv_p).
      12              :  *   - Cannot verify that ciphertext actually differs from plaintext with
      13              :  *     uniform IVs (XOR symmetry with identity encrypt).
      14              :  *   - Round-trip works because encrypt/decrypt are symmetric under identity.
      15              :  */
      16              : 
      17              : #include "test_helpers.h"
      18              : #include "ige_aes.h"
      19              : #include "mock_crypto.h"
      20              : #include "crypto.h"
      21              : 
      22              : #include <stdlib.h>
      23              : #include <string.h>
      24              : 
      25            1 : void test_ige_encrypt_1block(void) {
      26            1 :     mock_crypto_reset();
      27            1 :     uint8_t key[32] = {0}, iv[32] = {0};
      28            1 :     uint8_t plain[16] = {1}, cipher[16];
      29              : 
      30            1 :     aes_ige_encrypt(plain, 16, key, iv, cipher);
      31            1 :     ASSERT(mock_crypto_encrypt_block_call_count() == 1,
      32              :            "1 block → 1 encrypt_block call");
      33              : }
      34              : 
      35            1 : void test_ige_encrypt_3blocks(void) {
      36            1 :     mock_crypto_reset();
      37            1 :     uint8_t key[32] = {0}, iv[32] = {0};
      38            1 :     uint8_t plain[48] = {0}, cipher[48];
      39              : 
      40            1 :     aes_ige_encrypt(plain, 48, key, iv, cipher);
      41            1 :     ASSERT(mock_crypto_encrypt_block_call_count() == 3,
      42              :            "3 blocks → 3 encrypt_block calls");
      43              : }
      44              : 
      45            1 : void test_ige_decrypt_2blocks(void) {
      46            1 :     mock_crypto_reset();
      47            1 :     uint8_t key[32] = {0}, iv[32] = {0};
      48            1 :     uint8_t cipher[32] = {0}, plain[32];
      49              : 
      50            1 :     aes_ige_decrypt(cipher, 32, key, iv, plain);
      51            1 :     ASSERT(mock_crypto_decrypt_block_call_count() == 2,
      52              :            "2 blocks → 2 decrypt_block calls");
      53              : }
      54              : 
      55            1 : void test_ige_set_encrypt_key(void) {
      56            1 :     mock_crypto_reset();
      57            1 :     uint8_t key[32] = {0}, iv[32] = {0};
      58            1 :     uint8_t plain[16] = {0}, cipher[16];
      59              : 
      60            1 :     aes_ige_encrypt(plain, 16, key, iv, cipher);
      61            1 :     ASSERT(mock_crypto_set_encrypt_key_call_count() == 1,
      62              :            "set_encrypt_key should be called once");
      63              : }
      64              : 
      65            1 : void test_ige_roundtrip_1block(void) {
      66              :     /* With identity mock, IGE is XOR-symmetric → round-trip works */
      67              :     uint8_t key[32], iv[32], plain[16], cipher[16], dec[16];
      68            1 :     memset(key, 0x42, 32);
      69            1 :     memset(iv, 0x55, 32);
      70           17 :     for (int i = 0; i < 16; i++) plain[i] = (uint8_t)i;
      71              : 
      72            1 :     aes_ige_encrypt(plain, 16, key, iv, cipher);
      73            1 :     aes_ige_decrypt(cipher, 16, key, iv, dec);
      74            1 :     ASSERT(memcmp(plain, dec, 16) == 0, "round-trip 1 block");
      75              : }
      76              : 
      77            1 : void test_ige_roundtrip_4blocks(void) {
      78              :     uint8_t key[32], iv[32], plain[64], cipher[64], dec[64];
      79            1 :     memset(key, 0xAB, 32);
      80            1 :     memset(iv, 0xCD, 32);
      81           65 :     for (int i = 0; i < 64; i++) plain[i] = (uint8_t)(i * 7);
      82              : 
      83            1 :     aes_ige_encrypt(plain, 64, key, iv, cipher);
      84            1 :     aes_ige_decrypt(cipher, 64, key, iv, dec);
      85            1 :     ASSERT(memcmp(plain, dec, 64) == 0, "round-trip 4 blocks");
      86              : }
      87              : 
      88            1 : void test_ige_null_safe(void) {
      89            1 :     uint8_t buf[16] = {0};
      90            1 :     aes_ige_encrypt(NULL, 16, buf, buf, buf);
      91            1 :     aes_ige_encrypt(buf, 0, buf, buf, buf);
      92            1 :     aes_ige_decrypt(NULL, 16, buf, buf, buf);
      93            1 :     aes_ige_decrypt(buf, 0, buf, buf, buf);
      94            1 :     ASSERT(1, "null/zero inputs should not crash");
      95              : }
      96              : 
      97            1 : void test_ige_unaligned_len(void) {
      98              :     /* QA-10: len must be a multiple of 16; otherwise the function must
      99              :      * return without reading past the buffer. Using tight 15/17/31 byte
     100              :      * buffers ensures ASAN would trip if we iterated past end. */
     101            1 :     mock_crypto_reset();
     102            1 :     uint8_t key[32] = {0}, iv[32] = {0};
     103            1 :     uint8_t plain15[15] = {0}, cipher15[15] = {0};
     104            1 :     uint8_t plain17[17] = {0}, cipher17[17] = {0};
     105            1 :     uint8_t plain31[31] = {0}, cipher31[31] = {0};
     106              : 
     107            1 :     aes_ige_encrypt(plain15, 15, key, iv, cipher15);
     108            1 :     aes_ige_encrypt(plain17, 17, key, iv, cipher17);
     109            1 :     aes_ige_encrypt(plain31, 31, key, iv, cipher31);
     110            1 :     aes_ige_decrypt(cipher15, 15, key, iv, plain15);
     111            1 :     aes_ige_decrypt(cipher17, 17, key, iv, plain17);
     112            1 :     aes_ige_decrypt(cipher31, 31, key, iv, plain31);
     113              : 
     114            1 :     ASSERT(mock_crypto_encrypt_block_call_count() == 0,
     115              :            "unaligned len → no encrypt_block calls");
     116            1 :     ASSERT(mock_crypto_decrypt_block_call_count() == 0,
     117              :            "unaligned len → no decrypt_block calls");
     118              : }
     119              : 
     120            1 : void test_ige(void) {
     121            1 :     RUN_TEST(test_ige_encrypt_1block);
     122            1 :     RUN_TEST(test_ige_encrypt_3blocks);
     123            1 :     RUN_TEST(test_ige_decrypt_2blocks);
     124            1 :     RUN_TEST(test_ige_set_encrypt_key);
     125            1 :     RUN_TEST(test_ige_roundtrip_1block);
     126            1 :     RUN_TEST(test_ige_roundtrip_4blocks);
     127            1 :     RUN_TEST(test_ige_null_safe);
     128            1 :     RUN_TEST(test_ige_unaligned_len);
     129            1 : }
        

Generated by: LCOV version 2.0-1