Files
2026-07-30 19:57:00 +05:30

848 lines
29 KiB
C

/**
* TEST PROGRAM: AES-GCM Authenticated Encryption/Decryption Test
* Environment: VxWorks 6.9, OpenSSL 3.5.0, 32-bit ARM
*
* Features: Positive tests + Negative tests for integrity validation
* - Modified ciphertext detection
* - Modified AAD detection
* - Modified tag detection
* - Wrong IV detection
*
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/rand.h>
/* ========== TEST DATA ========== */
/* Fixed key (16 bytes / 128 bits) for reproducibility */
static const unsigned char test_key[] = {
0x0A, 0x1B, 0x2C, 0x3D, 0x4E, 0x5F, 0x6A, 0x7B,
0x8C, 0x9D, 0x0E, 0x1F, 0x2A, 0x3B, 0x4C, 0x5D
};
/* Fixed IV (12 bytes / 96 bits) - GCM recommended length */
static const unsigned char test_iv[] = {
0x1A, 0x2B, 0x3C, 0x4D, 0x5E, 0x6F, 0x7A, 0x8B,
0x9C, 0x0D, 0x1E, 0x2F /* Added 0x2F for 12 bytes total */
};
/* Associated Data (AAD) - authenticated but not encrypted */
static const char* test_aad = "AAD-TEST-DATA-FOR-VXWORKS";
/* Plaintext test vectors */
static const char* test_plaintexts[] = {
"AES-GCM-Authenticated-Encryption-Test", /* 32 bytes */
"GCM-INTEGRITY-TEST-PATTERN-GCM-INTEGRITY-TEST-PATTERN-", /* 50+ bytes */
"", /* 0 bytes (empty) */
"X" /* 1 byte */
};
static const int test_plaintext_lengths[] = {32, 50, 0, 1};
/* ========== UTILITY FUNCTIONS ========== */
void print_hex(const char* label, const unsigned char* data, int len) {
printf("%s (%d bytes): ", label, len);
int i;
for (i = 0; i < len && i < 48; i++) {
printf("%02X", data[i]);
}
if (len > 48) printf("...");
printf("\n");
}
void print_hex_full(const char* label, const unsigned char* data, int len) {
printf("%s (%d bytes):\n", label, len);
int i;
for (i = 0; i < len; i++) {
printf("%02X", data[i]);
if ((i + 1) % 4 == 0 && i + 1 < len) {
printf(" ");
}
if ((i + 1) % 16 == 0 && i + 1 < len) {
printf("\n");
}
}
printf("\n");
}
void print_string(const char* label, const char* data, int len) {
printf("%s (%d bytes): ", label, len);
int i;
for (i = 0; i < len && i < 48; i++) {
if (data[i] >= 32 && data[i] <= 126)
printf("%c", data[i]);
else
printf(".");
}
if (len > 48) printf("...");
printf("\n");
}
void print_string_full(const char* label, const char* data, int len) {
printf("%s (%d bytes):\n", label, len);
printf(" String: \"");
int i;
for (i = 0; i < len; i++) {
if (data[i] >= 32 && data[i] <= 126)
printf("%c", data[i]);
else if (data[i] == '\0')
printf("\\0");
else
printf("\\x%02X", (unsigned char)data[i]);
}
printf("\"\n");
}
int compare_buffers(const unsigned char* buf1, const unsigned char* buf2, int len) {
return memcmp(buf1, buf2, len) == 0;
}
void flip_bit(unsigned char* buffer, int position) {
int byte_pos = position / 8;
int bit_pos = position % 8;
buffer[byte_pos] ^= (1 << bit_pos);
}
void print_openssl_errors(void) {
unsigned long err;
char err_buf[256];
while ((err = ERR_get_error()) != 0) {
ERR_error_string_n(err, err_buf, sizeof(err_buf));
printf("OpenSSL error: %s\n", err_buf);
}
}
/* ========== FILE COMPARISON FUNCTION ========== */
/**
* Compare two files byte by byte to check if they are identical
* Returns: 1 if files are identical, 0 otherwise
*/
int filesMatch(const char* f1, const char* f2)
{
int fd1, fd2, match = 1;
char c1, c2;
fd1 = open(f1, O_RDONLY, 0);
fd2 = open(f2, O_RDONLY, 0);
if (fd1 == -1 || fd2 == -1)
{
if (fd1 != -1) close(fd1);
if (fd2 != -1) close(fd2);
printf("ERROR: Cannot open one or both files\n");
return 0;
}
/* Compare byte by byte */
while (read(fd1, &c1, 1) == 1 && read(fd2, &c2, 1) == 1)
{
if (c1 != c2)
{
match = 0;
break;
}
}
/* If still matching, check if both files reached EOF */
if (match == 1)
{
int remaining1 = read(fd1, &c1, 1);
int remaining2 = read(fd2, &c2, 1);
if (remaining1 != 0 || remaining2 != 0)
match = 0;
}
close(fd1);
close(fd2);
printf(match ? "Files are IDENTICAL\n" : "Files are NOT IDENTICAL\n");
return match;
}
/* ========== CORE AES-GCM FUNCTIONS ========== */
/**
* Encrypt plaintext using AES-128-GCM
* Returns: ciphertext length (>=0), -1 on error
* Also outputs authentication tag
*/
int aes_gcm_encrypt(const unsigned char* plaintext, int plaintext_len,
const unsigned char* key, const unsigned char* iv, int iv_len,
const unsigned char* aad, int aad_len,
unsigned char** ciphertext, unsigned char** tag, int tag_len) {
EVP_CIPHER_CTX* ctx;
int len;
int ciphertext_len;
/* For empty plaintext, allocate at least 1 byte to avoid NULL issues */
int alloc_len = (plaintext_len > 0) ? plaintext_len : 1;
*ciphertext = (unsigned char*)malloc(alloc_len + 16);
*tag = (unsigned char*)malloc(tag_len);
if (*ciphertext == NULL || *tag == NULL) {
if (*ciphertext) free(*ciphertext);
if (*tag) free(*tag);
return -1;
}
ctx = EVP_CIPHER_CTX_new();
if (!ctx) {
free(*ciphertext);
free(*tag);
return -1;
}
/* Initialize encryption */
if (EVP_EncryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL) != 1) {
print_openssl_errors();
EVP_CIPHER_CTX_free(ctx);
free(*ciphertext);
free(*tag);
return -1;
}
/* Set IV length */
if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv_len, NULL) != 1) {
print_openssl_errors();
EVP_CIPHER_CTX_free(ctx);
free(*ciphertext);
free(*tag);
return -1;
}
/* Initialize key and IV */
if (EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv) != 1) {
print_openssl_errors();
EVP_CIPHER_CTX_free(ctx);
free(*ciphertext);
free(*tag);
return -1;
}
/* Add AAD (authenticated but not encrypted) */
if (aad && aad_len > 0) {
if (EVP_EncryptUpdate(ctx, NULL, &len, aad, aad_len) != 1) {
print_openssl_errors();
EVP_CIPHER_CTX_free(ctx);
free(*ciphertext);
free(*tag);
return -1;
}
}
/* Encrypt plaintext */
if (plaintext_len > 0) {
if (EVP_EncryptUpdate(ctx, *ciphertext, &len, plaintext, plaintext_len) != 1) {
print_openssl_errors();
EVP_CIPHER_CTX_free(ctx);
free(*ciphertext);
free(*tag);
return -1;
}
ciphertext_len = len;
} else {
ciphertext_len = 0;
}
/* Finalize encryption */
if (EVP_EncryptFinal_ex(ctx, *ciphertext + ciphertext_len, &len) != 1) {
print_openssl_errors();
EVP_CIPHER_CTX_free(ctx);
free(*ciphertext);
free(*tag);
return -1;
}
ciphertext_len += len;
/* Get authentication tag */
if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, tag_len, *tag) != 1) {
print_openssl_errors();
EVP_CIPHER_CTX_free(ctx);
free(*ciphertext);
free(*tag);
return -1;
}
EVP_CIPHER_CTX_free(ctx);
return ciphertext_len;
}
/**
* Decrypt ciphertext using AES-128-GCM
* Returns: plaintext length (>=0), -1 on error (including tag mismatch)
*/
int aes_gcm_decrypt(const unsigned char* ciphertext, int ciphertext_len,
const unsigned char* key, const unsigned char* iv, int iv_len,
const unsigned char* aad, int aad_len,
const unsigned char* tag, int tag_len,
unsigned char** plaintext) {
EVP_CIPHER_CTX* ctx;
int len;
int plaintext_len;
int ret;
/* For empty ciphertext, allocate at least 1 byte */
int alloc_len = (ciphertext_len > 0) ? ciphertext_len : 1;
*plaintext = (unsigned char*)malloc(alloc_len);
if (*plaintext == NULL) return -1;
ctx = EVP_CIPHER_CTX_new();
if (!ctx) {
free(*plaintext);
return -1;
}
/* Initialize decryption */
if (EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL) != 1) {
print_openssl_errors();
EVP_CIPHER_CTX_free(ctx);
free(*plaintext);
return -1;
}
/* Set IV length */
if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv_len, NULL) != 1) {
print_openssl_errors();
EVP_CIPHER_CTX_free(ctx);
free(*plaintext);
return -1;
}
/* Initialize key and IV */
if (EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv) != 1) {
print_openssl_errors();
EVP_CIPHER_CTX_free(ctx);
free(*plaintext);
return -1;
}
/* Add AAD */
if (aad && aad_len > 0) {
if (EVP_DecryptUpdate(ctx, NULL, &len, aad, aad_len) != 1) {
print_openssl_errors();
EVP_CIPHER_CTX_free(ctx);
free(*plaintext);
return -1;
}
}
/* Decrypt ciphertext */
if (ciphertext_len > 0) {
if (EVP_DecryptUpdate(ctx, *plaintext, &len, ciphertext, ciphertext_len) != 1) {
print_openssl_errors();
EVP_CIPHER_CTX_free(ctx);
free(*plaintext);
return -1;
}
plaintext_len = len;
} else {
plaintext_len = 0;
}
/* Set expected tag */
if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, tag_len, (void*)tag) != 1) {
print_openssl_errors();
EVP_CIPHER_CTX_free(ctx);
free(*plaintext);
return -1;
}
/* Finalize decryption - tag verification happens here */
ret = EVP_DecryptFinal_ex(ctx, *plaintext + plaintext_len, &len);
EVP_CIPHER_CTX_free(ctx);
if (ret != 1) {
/* Tag mismatch or other error */
free(*plaintext);
*plaintext = NULL;
return -1;
}
plaintext_len += len;
return plaintext_len;
}
/* ========== POSITIVE TEST (Normal Operation) ========== */
int run_positive_test(const char* test_name, const unsigned char* plaintext, int plaintext_len,
const unsigned char* key, const unsigned char* iv, int iv_len,
const char* aad, int aad_len) {
unsigned char* ciphertext = NULL;
unsigned char* decrypted = NULL;
unsigned char* tag = NULL;
int ciphertext_len;
int decrypted_len;
int tag_len = 16; /* 128-bit tag */
int pass = 1;
int is_empty = (plaintext_len == 0);
printf("\n========================================\n");
printf("POSITIVE TEST: %s\n", test_name);
printf("Plaintext length: %d bytes\n", plaintext_len);
if (plaintext_len > 0 && plaintext_len <= 64) {
print_string_full("Original Plaintext", (const char*)plaintext, plaintext_len);
print_hex_full("Original Plaintext (Hex)", plaintext, plaintext_len);
} else if (is_empty) {
printf("Plaintext: (empty)\n");
}
printf("AAD: %s\n", aad);
/* STEP 1: Encrypt */
printf("\n[STEP 1] AES-GCM Encrypting...\n");
ciphertext_len = aes_gcm_encrypt(plaintext, plaintext_len, key, iv, iv_len,
(const unsigned char*)aad, aad_len,
&ciphertext, &tag, tag_len);
if (ciphertext_len < 0) {
printf("FAIL: Encryption failed (ciphertext_len=%d)\n", ciphertext_len);
pass = 0;
goto cleanup;
}
if (is_empty && ciphertext_len == 0) {
printf("PASS: Empty plaintext encryption successful (ciphertext empty, tag generated)\n");
} else {
printf("PASS: Encryption successful\n");
}
printf(" Ciphertext length: %d bytes\n", ciphertext_len);
printf(" Tag length: %d bytes\n", tag_len);
print_hex_full("Generated Tag", tag, tag_len);
/* Print FULL ciphertext */
if (ciphertext_len > 0) {
print_hex_full("Ciphertext (Encrypted Output)", ciphertext, ciphertext_len);
} else {
printf("Ciphertext: (empty)\n");
}
/* STEP 2: Verify ciphertext != plaintext */
printf("\n[STEP 2] Verifying ciphertext != plaintext...\n");
if (is_empty) {
printf("PASS: Both plaintext and ciphertext are empty (trivially not identical)\n");
} else if (plaintext_len == ciphertext_len && compare_buffers(plaintext, ciphertext, plaintext_len)) {
printf("FAIL: Ciphertext is identical to plaintext\n");
pass = 0;
goto cleanup;
} else {
printf("PASS: Ciphertext is different from plaintext\n");
}
/* STEP 3: Decrypt with valid inputs */
printf("\n[STEP 3] AES-GCM Decrypting with valid tag...\n");
decrypted_len = aes_gcm_decrypt(ciphertext, ciphertext_len, key, iv, iv_len,
(const unsigned char*)aad, aad_len,
tag, tag_len, &decrypted);
if (decrypted_len < 0) {
printf("FAIL: Decryption failed (decrypted_len=%d) - Tag mismatch?\n", decrypted_len);
pass = 0;
goto cleanup;
}
if (is_empty && decrypted_len == 0) {
printf("PASS: Empty plaintext decryption successful\n");
} else {
printf("PASS: Decryption successful\n");
}
printf(" Decrypted length: %d bytes\n", decrypted_len);
/* Print FULL decrypted plaintext */
if (decrypted_len > 0) {
print_string_full("Decrypted Plaintext (Recovered)", (const char*)decrypted, decrypted_len);
print_hex_full("Decrypted Plaintext (Hex)", decrypted, decrypted_len);
} else {
printf("Decrypted plaintext: (empty)\n");
}
/* STEP 4: Verify decrypted != ciphertext */
printf("\n[STEP 4] Verifying decrypted text != ciphertext...\n");
if (is_empty) {
printf("PASS: Both are empty (trivially not identical)\n");
} else if (decrypted_len == ciphertext_len && compare_buffers(decrypted, ciphertext, decrypted_len)) {
printf("FAIL: Decrypted text is identical to ciphertext\n");
pass = 0;
goto cleanup;
} else {
printf("PASS: Decrypted text is different from ciphertext\n");
}
/* STEP 5: Verify decrypted == original plaintext */
printf("\n[STEP 5] Verifying decrypted text matches original plaintext...\n");
if (decrypted_len != plaintext_len) {
printf("FAIL: Length mismatch (plaintext=%d, decrypted=%d)\n",
plaintext_len, decrypted_len);
pass = 0;
goto cleanup;
}
if (plaintext_len > 0 && !compare_buffers(plaintext, decrypted, plaintext_len)) {
printf("FAIL: Decrypted text does NOT match original plaintext\n");
pass = 0;
goto cleanup;
}
printf("PASS: Decrypted text matches original plaintext exactly\n");
printf("\n*** POSITIVE TEST RESULT: %s ***\n", pass ? "PASS" : "FAIL");
cleanup:
if (ciphertext) free(ciphertext);
if (decrypted) free(decrypted);
if (tag) free(tag);
return pass;
}
/* ========== NEGATIVE TESTS (Integrity Protection) ========== */
/* Negative Test 1: Modified Ciphertext */
int run_negative_test_modified_ciphertext(const unsigned char* plaintext, int plaintext_len,
const unsigned char* key, const unsigned char* iv, int iv_len,
const char* aad, int aad_len) {
unsigned char* ciphertext = NULL;
unsigned char* decrypted = NULL;
unsigned char* tag = NULL;
int ciphertext_len;
int decrypted_len;
int tag_len = 16;
int pass = 1;
printf("\n========================================\n");
printf("NEGATIVE TEST N1: Modified Ciphertext\n");
printf("Expected: Decryption should FAIL due to tag mismatch\n");
/* First, encrypt normally */
ciphertext_len = aes_gcm_encrypt(plaintext, plaintext_len, key, iv, iv_len,
(const unsigned char*)aad, aad_len,
&ciphertext, &tag, tag_len);
if (ciphertext_len < 0) {
printf("FAIL: Setup encryption failed\n");
return 0;
}
/* Only modify if ciphertext has content */
if (ciphertext_len > 0) {
printf("\nOriginal ciphertext (first 16 bytes): ");
int i;
for (i = 0; i < 16 && i < ciphertext_len; i++) {
printf("%02X", ciphertext[i]);
}
printf("\n");
printf("Modifying ciphertext: flipping bit 0 of byte 0\n");
flip_bit(ciphertext, 0);
printf("Modified ciphertext (first 16 bytes): ");
for (i = 0; i < 16 && i < ciphertext_len; i++) {
printf("%02X", ciphertext[i]);
}
printf("\n");
} else {
printf("Ciphertext is empty, skipping modification (test not applicable)\n");
printf("PASS: Empty ciphertext cannot be modified - test skipped\n");
if (ciphertext) free(ciphertext);
if (tag) free(tag);
return 1;
}
/* Try to decrypt with modified ciphertext */
decrypted_len = aes_gcm_decrypt(ciphertext, ciphertext_len, key, iv, iv_len,
(const unsigned char*)aad, aad_len,
tag, tag_len, &decrypted);
if (decrypted_len == -1) {
printf("\nPASS: Decryption correctly FAILED (tag mismatch detected)\n");
} else {
printf("\nFAIL: Decryption SUCCEEDED when it should have failed!\n");
if (decrypted_len >= 0) {
printf(" Decrypted %d bytes of invalid data!\n", decrypted_len);
}
pass = 0;
}
if (ciphertext) free(ciphertext);
if (decrypted) free(decrypted);
if (tag) free(tag);
printf("*** NEGATIVE TEST RESULT: %s ***\n", pass ? "PASS" : "FAIL");
return pass;
}
/* Negative Test 2: Modified AAD */
int run_negative_test_modified_aad(const unsigned char* plaintext, int plaintext_len,
const unsigned char* key, const unsigned char* iv, int iv_len,
const char* aad, int aad_len) {
unsigned char* ciphertext = NULL;
unsigned char* decrypted = NULL;
unsigned char* tag = NULL;
int ciphertext_len;
int decrypted_len;
int tag_len = 16;
int pass = 1;
char modified_aad[256];
printf("\n========================================\n");
printf("NEGATIVE TEST N2: Modified AAD\n");
printf("Expected: Decryption should FAIL due to tag mismatch\n");
/* First, encrypt normally with original AAD */
ciphertext_len = aes_gcm_encrypt(plaintext, plaintext_len, key, iv, iv_len,
(const unsigned char*)aad, aad_len,
&ciphertext, &tag, tag_len);
if (ciphertext_len < 0) {
printf("FAIL: Setup encryption failed\n");
return 0;
}
/* Modify AAD - change one character */
strcpy(modified_aad, aad);
modified_aad[0] = (modified_aad[0] == 'A') ? 'B' : 'A';
printf("\nOriginal AAD: %s\n", aad);
printf("Modified AAD: %s\n", modified_aad);
/* Try to decrypt with modified AAD */
decrypted_len = aes_gcm_decrypt(ciphertext, ciphertext_len, key, iv, iv_len,
(const unsigned char*)modified_aad, strlen(modified_aad),
tag, tag_len, &decrypted);
if (decrypted_len == -1) {
printf("\nPASS: Decryption correctly FAILED (AAD mismatch detected)\n");
} else {
printf("\nFAIL: Decryption SUCCEEDED with modified AAD!\n");
pass = 0;
}
if (ciphertext) free(ciphertext);
if (decrypted) free(decrypted);
if (tag) free(tag);
printf("*** NEGATIVE TEST RESULT: %s ***\n", pass ? "PASS" : "FAIL");
return pass;
}
/* Negative Test 3: Modified Tag */
int run_negative_test_modified_tag(const unsigned char* plaintext, int plaintext_len,
const unsigned char* key, const unsigned char* iv, int iv_len,
const char* aad, int aad_len) {
unsigned char* ciphertext = NULL;
unsigned char* decrypted = NULL;
unsigned char* tag = NULL;
int ciphertext_len;
int decrypted_len;
int tag_len = 16;
int pass = 1;
unsigned char original_tag[16];
printf("\n========================================\n");
printf("NEGATIVE TEST N3: Modified Authentication Tag\n");
printf("Expected: Decryption should FAIL due to tag mismatch\n");
/* First, encrypt normally */
ciphertext_len = aes_gcm_encrypt(plaintext, plaintext_len, key, iv, iv_len,
(const unsigned char*)aad, aad_len,
&ciphertext, &tag, tag_len);
if (ciphertext_len < 0) {
printf("FAIL: Setup encryption failed\n");
return 0;
}
/* Save original tag for display */
memcpy(original_tag, tag, tag_len);
printf("\nOriginal tag: ");
int i;
for (i = 0; i < tag_len; i++) {
printf("%02X", original_tag[i]);
}
printf("\n");
/* Modify tag - flip first bit */
printf("Modifying tag: flipping bit 0 of byte 0\n");
flip_bit(tag, 0);
printf("Modified tag: ");
for (i = 0; i < tag_len; i++) {
printf("%02X", tag[i]);
}
printf("\n");
/* Try to decrypt with modified tag */
decrypted_len = aes_gcm_decrypt(ciphertext, ciphertext_len, key, iv, iv_len,
(const unsigned char*)aad, aad_len,
tag, tag_len, &decrypted);
if (decrypted_len == -1) {
printf("\nPASS: Decryption correctly FAILED (modified tag detected)\n");
} else {
printf("\nFAIL: Decryption SUCCEEDED with modified tag!\n");
pass = 0;
}
if (ciphertext) free(ciphertext);
if (decrypted) free(decrypted);
if (tag) free(tag);
printf("*** NEGATIVE TEST RESULT: %s ***\n", pass ? "PASS" : "FAIL");
return pass;
}
/* Negative Test 4: Wrong IV */
int run_negative_test_wrong_iv(const unsigned char* plaintext, int plaintext_len,
const unsigned char* key, const unsigned char* iv, int iv_len,
const char* aad, int aad_len) {
unsigned char* ciphertext = NULL;
unsigned char* decrypted = NULL;
unsigned char* tag = NULL;
unsigned char wrong_iv[12];
int ciphertext_len;
int decrypted_len;
int tag_len = 16;
int pass = 1;
printf("\n========================================\n");
printf("NEGATIVE TEST N4: Wrong IV\n");
printf("Expected: Decryption should FAIL due to tag mismatch\n");
/* First, encrypt normally */
ciphertext_len = aes_gcm_encrypt(plaintext, plaintext_len, key, iv, iv_len,
(const unsigned char*)aad, aad_len,
&ciphertext, &tag, tag_len);
if (ciphertext_len < 0) {
printf("FAIL: Setup encryption failed\n");
return 0;
}
/* Create wrong IV (different from original) */
memset(wrong_iv, 0xFF, sizeof(wrong_iv));
printf("\nOriginal IV: ");
int i;
for (i = 0; i < iv_len; i++) {
printf("%02X", iv[i]);
}
printf("\n");
printf("Wrong IV: ");
for (i = 0; i < iv_len; i++) {
printf("%02X", wrong_iv[i]);
}
printf("\n");
/* Try to decrypt with wrong IV */
decrypted_len = aes_gcm_decrypt(ciphertext, ciphertext_len, key, wrong_iv, iv_len,
(const unsigned char*)aad, aad_len,
tag, tag_len, &decrypted);
if (decrypted_len == -1) {
printf("\nPASS: Decryption correctly FAILED (wrong IV detected)\n");
} else {
printf("\nFAIL: Decryption SUCCEEDED with wrong IV!\n");
pass = 0;
}
if (ciphertext) free(ciphertext);
if (decrypted) free(decrypted);
if (tag) free(tag);
printf("*** NEGATIVE TEST RESULT: %s ***\n", pass ? "PASS" : "FAIL");
return pass;
}
/* ========== MAIN TEST ENTRY POINT ========== */
int test_aes_gcm(void) {
int positive_passed = 0;
int positive_total = 4;
int negative_passed = 0;
int negative_total = 4;
int i;
printf("\n");
printf("=================================================\n");
printf(" AES-GCM Authenticated Encryption Test Suite\n");
printf(" Environment: VxWorks 6.9 + OpenSSL 3.5.0\n");
printf(" Algorithm: AES-128-GCM | IV: 96 bits | Tag: 128 bits\n");
printf("=================================================\n");
printf("\n");
printf("+-------------------------------------------------+\n");
printf("| POSITIVE TESTS (Normal Operation) |\n");
printf("+-------------------------------------------------+\n");
/* Initialize OpenSSL */
OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();
/* Run positive tests */
for (i = 0; i < positive_total; i++) {
if (run_positive_test(test_plaintexts[i],
(const unsigned char*)test_plaintexts[i],
test_plaintext_lengths[i],
test_key, test_iv, sizeof(test_iv),
test_aad, strlen(test_aad))) {
positive_passed++;
}
}
/* Use first plaintext for negative tests (32 bytes) */
const unsigned char* neg_plaintext = (const unsigned char*)test_plaintexts[0];
int neg_plaintext_len = test_plaintext_lengths[0];
printf("\n");
printf("+-------------------------------------------------+\n");
printf("| NEGATIVE TESTS (Integrity Protection) |\n");
printf("+-------------------------------------------------+\n");
/* Run negative tests */
if (run_negative_test_modified_ciphertext(neg_plaintext, neg_plaintext_len,
test_key, test_iv, sizeof(test_iv),
test_aad, strlen(test_aad))) {
negative_passed++;
}
if (run_negative_test_modified_aad(neg_plaintext, neg_plaintext_len,
test_key, test_iv, sizeof(test_iv),
test_aad, strlen(test_aad))) {
negative_passed++;
}
if (run_negative_test_modified_tag(neg_plaintext, neg_plaintext_len,
test_key, test_iv, sizeof(test_iv),
test_aad, strlen(test_aad))) {
negative_passed++;
}
if (run_negative_test_wrong_iv(neg_plaintext, neg_plaintext_len,
test_key, test_iv, sizeof(test_iv),
test_aad, strlen(test_aad))) {
negative_passed++;
}
/* Summary */
printf("\n");
printf("=================================================\n");
printf(" TEST SUMMARY\n");
printf("=================================================\n");
printf(" Positive Tests: %d passed, %d failed\n", positive_passed, positive_total - positive_passed);
printf(" Negative Tests: %d passed, %d failed\n", negative_passed, negative_total - negative_passed);
printf("=================================================\n");
if (positive_passed == positive_total && negative_passed == negative_total) {
printf("\n*** ALL TESTS PASSED ***\n");
printf(" - All positive tests passed (including empty plaintext)\n");
printf(" - All negative tests correctly detected integrity violations\n");
return 0;
} else {
printf("\n*** SOME TESTS FAILED ***\n");
if (positive_passed != positive_total) {
printf(" - Positive test failure(s)\n");
}
if (negative_passed != negative_total) {
printf(" - Negative test failure(s) - integrity protection may be broken\n");
}
return 1;
}
}
/* ========== VXWORKS SPAWN ENTRY ========== */
void test_aes_gcm_entry(void) {
printf("\n[VxWorks] Starting AES-GCM test program...\n");
test_aes_gcm();
printf("\n[VxWorks] Test program completed.\n");
}