mirror of
https://github.com/jedisct1/libsodium.git
synced 2026-08-25 08:37:13 +09:00
319 lines
10 KiB
C
319 lines
10 KiB
C
#define TEST_NAME "ipcrypt"
|
|
#include "cmptest.h"
|
|
|
|
static void
|
|
dump_hex(const unsigned char *data, size_t len)
|
|
{
|
|
char hex[129];
|
|
|
|
sodium_bin2hex(hex, sizeof hex, data, len);
|
|
printf("%s\n", hex);
|
|
}
|
|
|
|
int
|
|
main(void)
|
|
{
|
|
unsigned char key[crypto_ipcrypt_KEYBYTES];
|
|
unsigned char ndx_key[crypto_ipcrypt_NDX_KEYBYTES];
|
|
unsigned char pfx_key[crypto_ipcrypt_PFX_KEYBYTES];
|
|
unsigned char input[crypto_ipcrypt_BYTES];
|
|
unsigned char output[crypto_ipcrypt_BYTES];
|
|
unsigned char nd_output[crypto_ipcrypt_ND_OUTPUTBYTES];
|
|
unsigned char ndx_output[crypto_ipcrypt_NDX_OUTPUTBYTES];
|
|
unsigned char pfx_output[crypto_ipcrypt_PFX_BYTES];
|
|
unsigned char tweak_nd[crypto_ipcrypt_ND_TWEAKBYTES];
|
|
unsigned char tweak_ndx[crypto_ipcrypt_NDX_TWEAKBYTES];
|
|
unsigned char decrypted[crypto_ipcrypt_BYTES];
|
|
unsigned char encrypted1[crypto_ipcrypt_PFX_BYTES];
|
|
unsigned char encrypted2[crypto_ipcrypt_PFX_BYTES];
|
|
size_t i;
|
|
|
|
printf("crypto_ipcrypt_BYTES: %zu\n", crypto_ipcrypt_bytes());
|
|
printf("crypto_ipcrypt_KEYBYTES: %zu\n", crypto_ipcrypt_keybytes());
|
|
printf("crypto_ipcrypt_ND_KEYBYTES: %zu\n", crypto_ipcrypt_nd_keybytes());
|
|
printf("crypto_ipcrypt_ND_TWEAKBYTES: %zu\n", crypto_ipcrypt_nd_tweakbytes());
|
|
printf("crypto_ipcrypt_ND_INPUTBYTES: %zu\n", crypto_ipcrypt_nd_inputbytes());
|
|
printf("crypto_ipcrypt_ND_OUTPUTBYTES: %zu\n", crypto_ipcrypt_nd_outputbytes());
|
|
printf("crypto_ipcrypt_NDX_KEYBYTES: %zu\n", crypto_ipcrypt_ndx_keybytes());
|
|
printf("crypto_ipcrypt_NDX_TWEAKBYTES: %zu\n", crypto_ipcrypt_ndx_tweakbytes());
|
|
printf("crypto_ipcrypt_NDX_INPUTBYTES: %zu\n", crypto_ipcrypt_ndx_inputbytes());
|
|
printf("crypto_ipcrypt_NDX_OUTPUTBYTES: %zu\n", crypto_ipcrypt_ndx_outputbytes());
|
|
printf("crypto_ipcrypt_PFX_KEYBYTES: %zu\n", crypto_ipcrypt_pfx_keybytes());
|
|
printf("crypto_ipcrypt_PFX_BYTES: %zu\n", crypto_ipcrypt_pfx_bytes());
|
|
|
|
/* Test 1: Format-preserving encryption with known key/input */
|
|
memset(key, 0x00, sizeof key);
|
|
key[0] = 0x01;
|
|
key[1] = 0x02;
|
|
key[2] = 0x03;
|
|
key[3] = 0x04;
|
|
key[4] = 0x05;
|
|
key[5] = 0x06;
|
|
key[6] = 0x07;
|
|
key[7] = 0x08;
|
|
key[8] = 0x09;
|
|
key[9] = 0x0a;
|
|
key[10] = 0x0b;
|
|
key[11] = 0x0c;
|
|
key[12] = 0x0d;
|
|
key[13] = 0x0e;
|
|
key[14] = 0x0f;
|
|
key[15] = 0x10;
|
|
|
|
/* IPv4-mapped IPv6 address: ::ffff:192.0.2.1 */
|
|
memset(input, 0x00, sizeof input);
|
|
input[10] = 0xff;
|
|
input[11] = 0xff;
|
|
input[12] = 0xc0; /* 192 */
|
|
input[13] = 0x00; /* 0 */
|
|
input[14] = 0x02; /* 2 */
|
|
input[15] = 0x01; /* 1 */
|
|
|
|
printf("\nTest 1: Format-preserving encryption\n");
|
|
printf("Key: ");
|
|
dump_hex(key, sizeof key);
|
|
printf("Input: ");
|
|
dump_hex(input, sizeof input);
|
|
|
|
crypto_ipcrypt_encrypt(output, input, key);
|
|
printf("Encrypted: ");
|
|
dump_hex(output, sizeof output);
|
|
|
|
crypto_ipcrypt_decrypt(decrypted, output, key);
|
|
printf("Decrypted: ");
|
|
dump_hex(decrypted, sizeof decrypted);
|
|
|
|
if (memcmp(input, decrypted, sizeof input) != 0) {
|
|
printf("FAILED: Decrypted does not match input\n");
|
|
return 1;
|
|
}
|
|
printf("OK: Round-trip successful\n");
|
|
|
|
/* Test 2: Non-deterministic encryption (ND mode with 8-byte tweak) */
|
|
memset(tweak_nd, 0, sizeof tweak_nd);
|
|
tweak_nd[0] = 0xaa;
|
|
tweak_nd[1] = 0xbb;
|
|
tweak_nd[2] = 0xcc;
|
|
tweak_nd[3] = 0xdd;
|
|
tweak_nd[4] = 0xee;
|
|
tweak_nd[5] = 0xff;
|
|
tweak_nd[6] = 0x11;
|
|
tweak_nd[7] = 0x22;
|
|
|
|
printf("\nTest 2: Non-deterministic encryption (ND mode)\n");
|
|
printf("Tweak: ");
|
|
dump_hex(tweak_nd, sizeof tweak_nd);
|
|
|
|
crypto_ipcrypt_nd_encrypt(nd_output, input, tweak_nd, key);
|
|
printf("ND Encrypted: ");
|
|
dump_hex(nd_output, sizeof nd_output);
|
|
|
|
crypto_ipcrypt_nd_decrypt(decrypted, nd_output, key);
|
|
printf("ND Decrypted: ");
|
|
dump_hex(decrypted, sizeof decrypted);
|
|
|
|
if (memcmp(input, decrypted, sizeof input) != 0) {
|
|
printf("FAILED: ND decrypted does not match input\n");
|
|
return 1;
|
|
}
|
|
printf("OK: ND round-trip successful\n");
|
|
|
|
/* Test 3: Non-deterministic encryption with extended tweak (NDX mode) */
|
|
memset(ndx_key, 0x00, sizeof ndx_key);
|
|
for (i = 0; i < sizeof ndx_key; i++) {
|
|
ndx_key[i] = (unsigned char) (i + 1);
|
|
}
|
|
|
|
memset(tweak_ndx, 0, sizeof tweak_ndx);
|
|
for (i = 0; i < sizeof tweak_ndx; i++) {
|
|
tweak_ndx[i] = (unsigned char) (0xaa + i);
|
|
}
|
|
|
|
printf("\nTest 3: Non-deterministic encryption (NDX mode with 16-byte tweak)\n");
|
|
printf("NDX Key: ");
|
|
dump_hex(ndx_key, sizeof ndx_key);
|
|
printf("NDX Tweak: ");
|
|
dump_hex(tweak_ndx, sizeof tweak_ndx);
|
|
|
|
crypto_ipcrypt_ndx_encrypt(ndx_output, input, tweak_ndx, ndx_key);
|
|
printf("NDX Encrypted: ");
|
|
dump_hex(ndx_output, sizeof ndx_output);
|
|
|
|
crypto_ipcrypt_ndx_decrypt(decrypted, ndx_output, ndx_key);
|
|
printf("NDX Decrypted: ");
|
|
dump_hex(decrypted, sizeof decrypted);
|
|
|
|
if (memcmp(input, decrypted, sizeof input) != 0) {
|
|
printf("FAILED: NDX decrypted does not match input\n");
|
|
return 1;
|
|
}
|
|
printf("OK: NDX round-trip successful\n");
|
|
|
|
/* Test 4: Keygen functions - skip random output in .exp */
|
|
printf("\nTest 4: Key generation\n");
|
|
crypto_ipcrypt_keygen(key);
|
|
printf("Random key generated (skipped in output)\n");
|
|
|
|
crypto_ipcrypt_ndx_keygen(ndx_key);
|
|
printf("Random NDX key generated (skipped in output)\n");
|
|
|
|
/* Test 5: Different inputs produce different outputs */
|
|
printf("\nTest 5: Different inputs produce different outputs\n");
|
|
memset(key, 0x42, sizeof key);
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
memset(input, 0, sizeof input);
|
|
input[10] = 0xff;
|
|
input[11] = 0xff;
|
|
input[15] = (unsigned char) i;
|
|
|
|
crypto_ipcrypt_encrypt(output, input, key);
|
|
printf("Input[%zu]: ", i);
|
|
dump_hex(input, sizeof input);
|
|
dump_hex(output, sizeof output);
|
|
}
|
|
|
|
/* Test 6: Verify deterministic encryption */
|
|
printf("\nTest 6: Verify deterministic encryption\n");
|
|
memset(key, 0x55, sizeof key);
|
|
memset(input, 0xaa, sizeof input);
|
|
|
|
crypto_ipcrypt_encrypt(output, input, key);
|
|
crypto_ipcrypt_encrypt(decrypted, input, key);
|
|
|
|
if (memcmp(output, decrypted, sizeof output) != 0) {
|
|
printf("FAILED: Deterministic encryption produced different outputs\n");
|
|
return 1;
|
|
}
|
|
printf("OK: Deterministic encryption verified\n");
|
|
|
|
printf("\nTest 7: In-place encryption and decryption\n");
|
|
|
|
crypto_ipcrypt_encrypt(output, input, key);
|
|
memcpy(decrypted, input, sizeof input);
|
|
crypto_ipcrypt_encrypt(decrypted, decrypted, key);
|
|
if (memcmp(output, decrypted, sizeof output) != 0) {
|
|
printf("FAILED: In-place encryption differs from out-of-place\n");
|
|
return 1;
|
|
}
|
|
crypto_ipcrypt_decrypt(decrypted, decrypted, key);
|
|
if (memcmp(input, decrypted, sizeof input) != 0) {
|
|
printf("FAILED: In-place decryption does not match original\n");
|
|
return 1;
|
|
}
|
|
printf("OK: In-place round-trip successful\n");
|
|
|
|
/* Test 8: Prefix-preserving encryption (PFX mode) */
|
|
printf("\nTest 8: Prefix-preserving encryption (PFX mode)\n");
|
|
|
|
/* Test vector from the specification:
|
|
* Key: 0123456789abcdeffedcba98765432101032547698badcfeefcdab8967452301
|
|
* Input IP: 0.0.0.0 (IPv4-mapped)
|
|
* Expected: 151.82.155.134
|
|
*/
|
|
sodium_hex2bin(pfx_key, sizeof pfx_key,
|
|
"0123456789abcdeffedcba98765432101032547698badcfeefcdab8967452301",
|
|
64, NULL, NULL, NULL);
|
|
|
|
memset(input, 0, sizeof input);
|
|
input[10] = 0xff;
|
|
input[11] = 0xff;
|
|
/* 0.0.0.0 */
|
|
|
|
printf("PFX Key: ");
|
|
dump_hex(pfx_key, sizeof pfx_key);
|
|
printf("Input (0.0.0.0): ");
|
|
dump_hex(input, sizeof input);
|
|
|
|
crypto_ipcrypt_pfx_encrypt(pfx_output, input, pfx_key);
|
|
printf("PFX Encrypted: ");
|
|
dump_hex(pfx_output, sizeof pfx_output);
|
|
|
|
crypto_ipcrypt_pfx_decrypt(decrypted, pfx_output, pfx_key);
|
|
printf("PFX Decrypted: ");
|
|
dump_hex(decrypted, sizeof decrypted);
|
|
|
|
if (memcmp(input, decrypted, sizeof input) != 0) {
|
|
printf("FAILED: PFX decrypted does not match input\n");
|
|
return 1;
|
|
}
|
|
printf("OK: PFX round-trip successful\n");
|
|
|
|
/* Test 9: Verify prefix preservation - IPs in same /24 should share encrypted prefix */
|
|
printf("\nTest 9: Verify prefix preservation\n");
|
|
|
|
/* Use test vector key from spec */
|
|
sodium_hex2bin(pfx_key, sizeof pfx_key,
|
|
"2b7e151628aed2a6abf7158809cf4f3ca9f5ba40db214c3798f2e1c23456789a",
|
|
64, NULL, NULL, NULL);
|
|
|
|
/* 10.0.0.47 */
|
|
memset(input, 0, sizeof input);
|
|
input[10] = 0xff;
|
|
input[11] = 0xff;
|
|
input[12] = 10;
|
|
input[13] = 0;
|
|
input[14] = 0;
|
|
input[15] = 47;
|
|
|
|
crypto_ipcrypt_pfx_encrypt(encrypted1, input, pfx_key);
|
|
printf("10.0.0.47 encrypted: ");
|
|
dump_hex(encrypted1, sizeof encrypted1);
|
|
|
|
/* 10.0.0.129 */
|
|
input[15] = 129;
|
|
|
|
crypto_ipcrypt_pfx_encrypt(encrypted2, input, pfx_key);
|
|
printf("10.0.0.129 encrypted: ");
|
|
dump_hex(encrypted2, sizeof encrypted2);
|
|
|
|
/* Check that the first 24 bits of the encrypted IPv4 addresses match (bytes 12-14) */
|
|
if (memcmp(encrypted1 + 12, encrypted2 + 12, 3) != 0) {
|
|
printf("FAILED: Prefix not preserved for /24 addresses\n");
|
|
return 1;
|
|
}
|
|
printf("OK: /24 prefix preserved\n");
|
|
|
|
/* Test 10: PFX keygen */
|
|
printf("\nTest 10: PFX key generation\n");
|
|
crypto_ipcrypt_pfx_keygen(pfx_key);
|
|
printf("Random PFX key generated (skipped in output)\n");
|
|
|
|
/* Test 11: IPv6 prefix preservation */
|
|
printf("\nTest 11: IPv6 prefix-preserving encryption\n");
|
|
|
|
sodium_hex2bin(pfx_key, sizeof pfx_key,
|
|
"2b7e151628aed2a6abf7158809cf4f3ca9f5ba40db214c3798f2e1c23456789a",
|
|
64, NULL, NULL, NULL);
|
|
|
|
/* 2001:db8::1 */
|
|
memset(input, 0, sizeof input);
|
|
input[0] = 0x20;
|
|
input[1] = 0x01;
|
|
input[2] = 0x0d;
|
|
input[3] = 0xb8;
|
|
input[15] = 0x01;
|
|
|
|
crypto_ipcrypt_pfx_encrypt(encrypted1, input, pfx_key);
|
|
printf("2001:db8::1 encrypted: ");
|
|
dump_hex(encrypted1, sizeof encrypted1);
|
|
|
|
/* 2001:db8::2 */
|
|
input[15] = 0x02;
|
|
|
|
crypto_ipcrypt_pfx_encrypt(encrypted2, input, pfx_key);
|
|
printf("2001:db8::2 encrypted: ");
|
|
dump_hex(encrypted2, sizeof encrypted2);
|
|
|
|
/* Check that the first 64 bits match (bytes 0-7 for /64 prefix) */
|
|
if (memcmp(encrypted1, encrypted2, 8) != 0) {
|
|
printf("FAILED: IPv6 /64 prefix not preserved\n");
|
|
return 1;
|
|
}
|
|
printf("OK: IPv6 /64 prefix preserved\n");
|
|
|
|
printf("\nAll tests passed!\n");
|
|
|
|
return 0;
|
|
}
|