/* API_examples.c */
/*
This source code carries out a series of tests on the
functions in CryptoSys API (diCryptoSys.dll).
The tests in themselves are pretty boring. Use the examples
as the basis for your hopefully-more-useful code.
It is not meant to be representative of good security coding.
There is minimal error checking here - we use assert as a blunt instrument -
and we make little or no effort to clean up passwords etc afterwards.
Use in conjunction with diCryptoSys.lib and diCryptoSys.dll (Version 4.2 or later)
Copyright (C) 2001-9 DI Management Services Pty Limited. All rights reserved.
Last updated:
$Date: 2009-03-18 17:57:00 $
$Revision: 4.2.0 $
*/
#if _MSC_VER >= 1100
/* Detect memory leaks in MSVC++ */
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#else
#include <stdlib.h>
#endif
#ifdef NDEBUG
/* Make sure assertion testing is turned on */
#undef NDEBUG
#endif
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include "diCryptoSys.h"
/* Compiler-specific explicit link to library.
This works in old MSVC and Borland for LIB in same dir - you may need to do otherwise
*/
#if !defined(unix) && (_MSC_VER < 1400)
#pragma comment(lib, ".\\diCryptoSys.lib")
#endif
/* SYSTEM-SPECIFIC DIR FNS:
* Used in `make_new_test_dir' and `remove_test_dir' only.
*/
#ifdef _MSC_VER
/* MSVC functions */
#include <direct.h>
#define MKDIR(d) _mkdir(d)
#define CHDIR(d) _chdir(d)
#define RMDIR(d) _rmdir(d)
#define GETCWD(od, n) _getcwd(od, n)
#elif __BORLANDC__
/* Borland functions */
#include <dir.h>
#define MKDIR(d) mkdir(d)
#define CHDIR(d) chdir(d)
#define RMDIR(d) rmdir(d)
#define GETCWD(od, n) getcwd(od, n)
#elif unix
/* Linux functions */
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#define MKDIR(d) mkdir(d, 0777)
#define CHDIR(d) chdir(d)
#define RMDIR(d) rmdir(d)
#define GETCWD(od, n) getcwd(od, n)
#else
/* Take a punt the compiler has inbuilt fns or die!
-- replace with your own here if necessary */
#define MKDIR(d) mkdir(d)
#define CHDIR(d) chdir(d)
#define RMDIR(d) rmdir(d)
#define GETCWD(od, n) getcwd(od, n)
#endif
#ifndef FALSE
#define FALSE (0)
#define TRUE (!FALSE)
#endif
/* FUNCTIONS TO CREATE AND REMOVE A TEST DIRECTORY */
/* Global variables */
char testdir[FILENAME_MAX];
char old_cwd[FILENAME_MAX];
char new_cwd[FILENAME_MAX];
int make_new_test_dir(void)
{
/*
(1) Try and create a sub-dir in current working dir
(2) If that fails, use _tempnam
*/
char hex[9];
char *tempname = "";
/* Use RNG to generate a 4-byte/8-hex char random address */
RNG_NonceDataHex(hex, sizeof(hex)-1, 4);
/* Create a test directory */
sprintf(testdir, ".\\apitest.%s", hex);
printf("Trying to create test directory '%s'...\n", testdir);
/* Use MS-system-specific fns to create and set as default dir */
if (MKDIR(testdir) != 0)
#ifdef _MSC_VER
{ /* Check in case we run this where we don't have permission */
printf("Unable to create test directory '%s'. Trying with _tempnam...\n", testdir);
/* Now try using _tempnam (making a copy) */
tempname = _tempnam("\\", "api");
strncpy(testdir, tempname, FILENAME_MAX-1);
free(tempname); /* _tempnam uses malloc */
if (MKDIR(testdir) != 0)
{
fprintf(stderr, "ERROR: unable to create a temp directory.");
exit(EXIT_FAILURE);
}
}
#else /* If not MSVC, we have just failed */
{
fprintf(stderr, "%s", tempname); /* Fudge to avoid compiler warning */
fprintf(stderr, "ERROR:unable to create a temp directory.");
exit(EXIT_FAILURE);
}
#endif
printf("Created test directory '%s' OK.\n", testdir);
/* Remember current working directory */
GETCWD(old_cwd, FILENAME_MAX-1);
/* Change CWD to our new temp dir */
CHDIR(testdir);
/* And check */
GETCWD(new_cwd, FILENAME_MAX-1);
printf("Current dir is '%s'\n", new_cwd);
return 0;
}
void remove_test_dir(char *dirname, char *old_cwd)
{
/* Use system commands to do the business
--see DELCMD macro above (NB strings concatenate) */
/* CAUTION: Use this carefully */
int res;
CHDIR(dirname);
if (!old_cwd)
CHDIR("..");
else
CHDIR(old_cwd);
res = RMDIR(dirname);
if (res == 0)
printf("Removed test directory OK.\n");
else
printf("ERROR: (%d) failed to remove test directory.\n", res);
}
/* UTILITIES USED IN THESE TESTS */
int create_hello_file(char *hello_file)
/* Create a 13-byte text file "hello world" plus CR-LF */
{
FILE *fp;
fp = fopen(hello_file, "wb");
assert (fp != NULL);
fprintf(fp, "hello world\r\n");
fclose(fp);
printf("Created 'hello.txt' as %s\n", hello_file);
return 0;
}
int create_nowis_file(char *filename)
/* Create a 32-byte text file without a CR-LF at end */
{
FILE *fp;
fp = fopen(filename, "wb");
assert (fp != NULL);
fprintf(fp, "Now is the time for all good men");
fclose(fp);
printf("Created 'nowis.txt' as %s\n", filename);
return 0;
}
int create_bin_file(char *bin_file)
/* Create a 512-byte binary file (0x00,0x01,0x02,...,0xFF)*2 */
{
int i, k;
FILE *fp;
fp = fopen(bin_file, "wb");
assert (fp != NULL);
for (k = 0; k < 2; k++)
for (i = 0; i < 256; i++)
fputc(i, fp);
fclose(fp);
printf("Created 'test.bin' as %s\n", bin_file);
return 0;
}
int file_exists(char *fname)
/* Returns true (1) if file exists or false (0) if it doesn't */
{
FILE *fp;
fp = fopen(fname, "rb");
if (fp == NULL)
return FALSE;
fclose(fp);
return TRUE;
}
int cmp_files(const char *file1, const char *file2)
/* Compares two binary files: returns 0 if identical
or 1 if not identical or -1 if file error
[2006-06-20] modified to check lengths first. */
{
FILE *fp1, *fp2;
int c1, c2;
long len1, len2;
int result = 0; /* Innocent until proven guilty */
fp1 = fopen(file1, "rb");
if (fp1 == NULL)
return -1;
fp2 = fopen(file2, "rb");
if (fp2 == NULL)
{
fclose(fp1);
return -1;
}
/* Compare lengths */
fseek(fp1, 0, SEEK_END);
len1 = ftell(fp1);
fseek(fp2, 0, SEEK_END);
len2 = ftell(fp2);
if (len1 != len2)
{
fclose(fp1);
fclose(fp2);
return 1;
}
rewind(fp1);
rewind(fp2);
while ((c1 = fgetc(fp1)) != EOF)
{
c2 = fgetc(fp2);
if (c1 != c2)
{ /* Found a mis-match */
result = 1;
break;
}
}
fclose(fp1);
fclose(fp2);
return result;
}
int cmp_file_with_hex(char *file, const char *hex_ok)
/* Returns zero if file contains exactly the bytes in hex_ok */
{
unsigned char *correct, *fbuf;
const char *cp;
long i, n, x, result;
FILE *fp;
char hex[3];
/* Convert correct hex string to bytes */
n = (long)strlen(hex_ok) / 2;
correct = malloc(n);
assert (correct != NULL);
fbuf = malloc(n);
assert (fbuf != NULL);
for (cp = hex_ok, i = 0; i < n; i++)
{
hex[0] = *cp++;
hex[1] = *cp++;
hex[2] = 0;
sscanf(hex, "%lx", &x);
correct[i] = (unsigned char)x;
}
/* Read in file to buffer */
fp = fopen(file, "rb");
assert (fp != NULL);
fread(fbuf, 1, n, fp);
/* Make sure we are end of file */
x = fgetc(fp);
/* Do we have a match? */
result = memcmp(fbuf, correct, n);
/* Clean up */
fclose(fp);
free(correct);
free(fbuf);
if (x != EOF)
return 1;
return result;
}
static int convert_hex_to_bytes(unsigned char bytes[], int maxbytes, const char *hexstr)
/* Converts null-terminated string of hex chars to an array of bytes up to maxbytes long
Returns # of bytes converted or -1 if error
*/
{
int i;
int len = (long)strlen(hexstr) / 2;
if (maxbytes < len) len = maxbytes;
for (i = 0; i < len; i++)
{
int t, v;
t = *hexstr++;
if ((t >= '0') && (t <= '9')) v = (t - '0') << 4;
else if ((t >= 'a') && (t <= 'f')) v = (t - 'a' + 10) << 4;
else if ((t >= 'A') && (t <= 'F')) v = (t - 'A' + 10) << 4;
else return -1;
t = *hexstr++;
if ((t >= '0') && (t <= '9')) v ^= (t - '0');
else if ((t >= 'a') && (t <= 'f')) v ^= (t - 'a' + 10);
else if ((t >= 'A') && (t <= 'F')) v ^= (t - 'A' + 10);
else return -1;
bytes[i] = (unsigned char)v;
}
return i;
}
/* Various versions that print a byte array in hex format */
static void pr_hexbytes(const unsigned char *bytes, int nbytes)
/* Print bytes in hex format + newline */
{
int i;
for (i = 0; i < nbytes; i++)
printf("%02X", bytes[i]);
printf("\n");
}
static void pr_bytesmsg(const char *msg, const unsigned char *bytes, long nbytes)
/* Ditto but print an optional message beforehand */
{
if (msg)
printf("%s", msg);
pr_hexbytes(bytes, nbytes);
}
static void pr_hexdump(const char *pre, const void *bytes, size_t nbytes, const char *post)
/* Print bytes as hex in blocks of 64 chars with optional "pre" and "post" strings */
{
size_t i;
const unsigned char *pb = (const unsigned char *)bytes;
if (pre)
printf("%s", pre);
for (i = 0; i < nbytes; i++)
{
if (i && (i % 32) == 0)
printf("\n");
printf("%02x", *pb++);
}
if (post)
printf("%s", post);
}
static char *lookup_error(int errcode)
/* Looks up description of error msg and returns
ptr to static string
*/
{
static char errmsg[128];
errmsg[0] = '\0';
API_ErrorLookup(errmsg, sizeof(errmsg), errcode);
return errmsg;
}
/* DES TESTS */
void test_DES_Hex(void)
{
char *testfn = "DES_Hex()";
char sHexKey[] = "0123456789abcdef";
/* "Now is t" in hex */
char sInput[] = "4E6F772069732074";
char sCorrect[] = "3FA40E8A984D4815";
char sOutput[sizeof(sInput)+1];
long lngRet;
printf("Testing %s...\n", testfn);
printf("KY=%s\n", sHexKey);
printf("PT=%s\n", sInput);
// Encrypt in one-off process
lngRet = DES_Hex(sOutput, sInput, sHexKey, ENCRYPT);
assert (lngRet == 0);
/* Check */
printf("CT=%s %ld\n", sOutput, lngRet);
printf("OK=%s\n", sCorrect);
assert (strcmp(sCorrect, sOutput) == 0);
// Now decrypt back to plain text using same buffer
lngRet = DES_Hex(sOutput, sOutput, sHexKey, DECRYPT);
assert (lngRet == 0);
printf("P'=%s %ld\n", sOutput, lngRet);
assert (strcmp(sInput, sOutput) == 0);
printf("...%s tested OK\n", testfn);
}
void test_DES_HexMode(void)
{
char *testfn = "DES_HexMode()";
long lngRet;
char sHexKey[] = "0123456789abcdef";
char sHexIV[] = "1234567890abcdef";
// "Now is the time for all good men"
char sInput[] = "4E6F77206973207468652074696D6520666F7220616C6C20";
char sCorrect[] = "E5C7CDDE872BF27C43E934008C389C0F683788499A7C05F6";
// Set sOutput to be same length as sInput
char sOutput[sizeof(sInput)+1];
printf("Testing %s...\n", testfn);
printf("KY=%s\n", sHexKey);
printf("IV=%s\n", sHexIV);
printf("PT=%s\n", sInput);
// Encrypt in one-off process
lngRet = DES_HexMode(sOutput, sInput, sHexKey, ENCRYPT, "CBC", sHexIV);
assert (lngRet == 0);
printf("CT=%s %ld\n", sOutput, lngRet);
printf("OK=%s\n", sCorrect);
assert (strcmp(sOutput, sCorrect) == 0);
// Now decrypt back to plain text
lngRet = DES_HexMode(sOutput, sOutput, sHexKey, DECRYPT, "cbc", sHexIV);
assert (lngRet == 0);
printf("P'=%s %ld\n", sOutput, lngRet);
assert (strcmp(sOutput, sInput) == 0);
printf("...%s tested OK\n", testfn);
}
void test_DES_UpdateHex(void)
{
long hContext;
long result;
char sKey[] = "0123456789ABCDEF";
char sInitV[] = "1234567890abcdef";
char sHexString[33];
char *correct;
printf("Testing DES_UpdateHex() in CBC mode ...\n");
hContext = DES_InitHex(sKey, ENCRYPT, "CBC", sInitV);
if (hContext == 0)
printf("DES_InitError=%ld\n", DES_InitError());
assert (hContext != 0);
/* First part: "Now is t" in hex (8 chars) */
strcpy(sHexString, "4e6f772069732074");
result = DES_UpdateHex(hContext, sHexString);
assert (result == 0);
correct = "E5C7CDDE872BF27C";
printf("Result =%s\n", sHexString);
printf("Correct=%s\n", correct);
assert (strcmp(sHexString, correct) == 0);
/* Second part: "he time for all " in hex (16 chars) */
strcpy(sHexString, "68652074696d6520666f7220616c6c20");
result = DES_UpdateHex(hContext, sHexString);
assert (result == 0);
correct = "43E934008C389C0F683788499A7C05F6";
printf("Result =%s\n", sHexString);
printf("Correct=%s\n", correct);
assert (strcmp(sHexString, correct) == 0);
result = DES_Final(hContext);
assert (result == 0);
/* Now decrypt */
hContext = DES_InitHex(sKey, DECRYPT, "CBC", sInitV);
if (hContext == 0)
printf("DES_InitError=%ld\n", DES_InitError());
assert (hContext != 0);
strcpy(sHexString, "E5C7CDDE872BF27C43E934008C389C0F");
result = DES_UpdateHex(hContext, sHexString);
assert (result == 0);
correct = "4E6F77206973207468652074696D6520";
printf("Result =%s\n", sHexString);
printf("Correct=%s\n", correct);
assert (strcmp(sHexString, correct) == 0);
strcpy(sHexString, "683788499A7C05F6");
result = DES_UpdateHex(hContext, sHexString);
assert (result == 0);
correct = "666F7220616C6C20";
printf("Result =%s\n", sHexString);
printf("Correct=%s\n", correct);
assert (strcmp(sHexString, correct) == 0);
result = DES_Final(hContext);
assert (result == 0);
printf("...DES_UpdateHex() tested OK\n");
}
void test_DES_FileHex(void)
{
char *testfn = "DES_FileHex()";
long lngRet;
// Construct full path names to files
char *strFileIn = "now.txt";
char *strFileOut = "DESnow.enc";
char *strFileChk = "DESnow.chk";
// Encrypt plaintext file to cipher
// WARNING: output file is just clobbered
char sHexKey[] = "0123456789ABCDEF";
printf("Testing %s...\n", testfn);
create_nowis_file(strFileIn);
lngRet = DES_FileHex(strFileOut, strFileIn, sHexKey,
ENCRYPT, "ECB", 0);
assert (lngRet == 0);
assert (cmp_file_with_hex(strFileOut,
"3FA40E8A984D48156A271787AB8883F9893D51EC4B563B53"
"73C1ADB2171F7894086F9A1D74C94D4E")
== 0);
// Now decrypt it
lngRet = DES_FileHex(strFileChk, strFileOut, sHexKey,
DECRYPT, "ECB", 0);
assert (lngRet == 0);
/* and check we got the plaintext we started with */
assert (cmp_files(strFileChk, strFileIn) == 0);
remove(strFileIn);
remove(strFileOut);
remove(strFileChk);
printf("...%s tested OK\n", testfn);
}
void test_DES_Bytes_rand(void)
/* Encrypt and decrypt random blocks with random keys */
{
char *testfn = "DES_Bytes_rand()";
unsigned char key[8];
unsigned char plain[1024];
unsigned char cipher[1024];
int i, j, n, m;
long result;
srand((unsigned)time(NULL));
printf("Testing DES_Bytes() with random blocks ...\n");
for (i = 0; i < 10; i++)
{
/* Create a random key */
for (j = 0; j < 8; j++)
key[j] = rand() & 0xFF;
/* Create some 'random' plaintext up to 1024 bytes long */
/* in a multiple of block size */
m = 1024 / 8;
n = ((rand() % m) + 1) * 8;
assert (n <= sizeof(plain));
for (j = 0; j < n; j++)
plain[j] = rand() & 0xFF;
/* Encrypt it into ciphertext */
result = DES_Bytes(cipher, plain, n, key, ENCRYPT);
assert (result == 0);
/* Now decipher (use same variable) */
result = DES_Bytes(cipher, cipher, n, key, DECRYPT);
assert (result == 0);
/* Check identical */
assert (memcmp(plain, cipher, n) == 0);
printf("%d(%d) ", i+1, n);
}
printf("...%s tested OK\n", testfn);
}
void test_DES_CheckKey(void)
{
char *testfn = "DES_CheckKey()";
long lngRet;
char *lpkey;
printf("Testing %s...\n", testfn);
/* Weak key */
lpkey = "0101010101010101";
lngRet = DES_CheckKeyHex(lpkey);
printf("%s is %s (%s)\n", lpkey, (lngRet == 0 ? "OK" : "BAD"), lookup_error(lngRet));
assert(lngRet != 0);
/* Valid key by one bit */
lpkey = "0101010101010102";
lngRet = DES_CheckKeyHex(lpkey);
printf("%s is %s (%s)\n", lpkey, (lngRet == 0 ? "OK" : "BAD"), lookup_error(lngRet));
assert(lngRet == 0);
/* Another weak key */
lpkey = "01fe01fe01fe01fe";
lngRet = DES_CheckKeyHex(lpkey);
printf("%s is %s (%s)\n", lpkey, (lngRet == 0 ? "OK" : "BAD"), lookup_error(lngRet));
assert(lngRet != 0);
/* Weak double key in 1st half*/
lpkey = "01010101010101010001112223334455";
lngRet = DES_CheckKeyHex(lpkey);
printf("%s is %s (%s)\n", lpkey, (lngRet == 0 ? "OK" : "BAD"), lookup_error(lngRet));
assert(lngRet != 0);
/* Weak triple key in 3rd part */
lpkey = "000111222333444555666777888999aa0101010101010101";
lngRet = DES_CheckKeyHex(lpkey);
printf("%s is %s (%s)\n", lpkey, (lngRet == 0 ? "OK" : "BAD"), lookup_error(lngRet));
assert(lngRet != 0);
/* Valid key */
lpkey = "000111222333444555666777888999aaabbbcccdddeeefff";
lngRet = DES_CheckKeyHex(lpkey);
printf("%s is %s (%s)\n", lpkey, (lngRet == 0 ? "OK" : "BAD"), lookup_error(lngRet));
assert(lngRet == 0);
/* Wrong key length (missing 'f' at end) */
lpkey = "000111222333444555666777888999aaabbbcccdddeeeff";
lngRet = DES_CheckKeyHex(lpkey);
printf("%s is %s (%s)\n", lpkey, (lngRet == 0 ? "OK" : "BAD"), lookup_error(lngRet));
assert(lngRet != 0);
printf("...%s tested OK\n", testfn);
}
/* TRIPLE DES (TDEA, 3DES) TESTS */
void test_TDEA_Hex(void)
{
char *testfn = "TDEA_Hex()";
char sHexKey[] = "010101010101010101010101010101010101010101010101";
char sInput[] = "8000000000000000";
char sCorrect[] = "95F8A5E5DD31D900";
char sOutput[sizeof(sInput)+1];
long lngRet;
printf("Testing %s...\n", testfn);
printf("KY=%s\n", sHexKey);
printf("PT=%s\n", sInput);
// Encrypt in one-off process
lngRet = TDEA_Hex(sOutput, sInput, sHexKey, ENCRYPT);
assert (lngRet == 0);
/* Check */
printf("CT=%s %ld\n", sOutput, lngRet);
printf("OK=%s\n", sCorrect);
assert (strcmp(sCorrect, sOutput) == 0);
// Now decrypt back to plain text using same buffer
lngRet = TDEA_Hex(sOutput, sOutput, sHexKey, DECRYPT);
assert (lngRet == 0);
printf("P'=%s %ld\n", sOutput, lngRet);
assert (strcmp(sInput, sOutput) == 0);
printf("...%s tested OK\n", testfn);
}
void test_TDEA_HexMode(void)
{
char *testfn = "TDEA_HexMode()";
long lngRet;
char sInput[] = "5468697320736F6D652073616D706520636F6E74656E742E0808080808080808";
char sHexKey[] = "737C791F25EAD0E04629254352F7DC6291E5CB26917ADA32";
char sHexIV[] = "B36B6BFB6231084E";
char sCorrect[] = "D76FD1178FBD02F84231F5C1D2A2F74A4159482964F675248254223DAF9AF8E4";
// Set sOutput to be same length as sInput
char sOutput[sizeof(sInput)+1];
printf("Testing %s...\n", testfn);
printf("KY=%s\n", sHexKey);
printf("IV=%s\n", sHexIV);
printf("PT=%s\n", sInput);
// Encrypt in one-off process
lngRet = TDEA_HexMode(sOutput, sInput, sHexKey, ENCRYPT, "CBC", sHexIV);
assert (lngRet == 0);
printf("CT=%s %ld\n", sOutput, lngRet);
printf("OK=%s\n", sCorrect);
assert (strcmp(sOutput, sCorrect) == 0);
// Now decrypt back to plain text
lngRet = TDEA_HexMode(sOutput, sOutput, sHexKey, DECRYPT, "cbc", sHexIV);
assert (lngRet == 0);
printf("P'=%s %ld\n", sOutput, lngRet);
assert (strcmp(sOutput, sInput) == 0);
printf("...%s tested OK\n", testfn);
}
void test_TDEA_FileHex(void)
{
char *testfn = "TDEA_FileHex()";
long lngRet;
// Construct full path names to files
char *strFileIn = "now.txt";
char *strFileOut = "TDEAnow.enc";
char *strFileChk = "TDEAnow.chk";
// Encrypt plaintext file to cipher
// WARNING: output file is just clobbered
char sHexKey[] = "fedcba9876543210fedcba9876543210fedcba9876543210";
printf("Testing %s...\n", testfn);
create_nowis_file(strFileIn);
lngRet = TDEA_FileHex(strFileOut, strFileIn, sHexKey,
ENCRYPT, "ECB", 0);
assert (lngRet == 0);
// Now decrypt it
lngRet = TDEA_FileHex(strFileChk, strFileOut, sHexKey,
DECRYPT, "ECB", 0);
assert (lngRet == 0);
/* and check we got the plaintext we started with */
assert (cmp_files(strFileChk, strFileIn) == 0);
remove(strFileIn);
remove(strFileOut);
remove(strFileChk);
printf("...%s tested OK\n", testfn);
}
void test_TDEA_Bytes_rand(void)
/* Encrypt and decrypt random blocks with random keys */
{
char *testfn = "TDEA_Bytes_rand()";
unsigned char key[24];
unsigned char plain[1024];
unsigned char cipher[1024];
int i, j, n, m;
long result;
srand((unsigned)time(NULL));
printf("Testing %s...\n", testfn);
for (i = 0; i < 10; i++)
{
/* Create a random key */
for (j = 0; j < 24; j++)
key[j] = rand() & 0xFF;
/* Create some 'random' plaintext up to 1024 bytes long */
/* in a multiple of block size */
m = 1024 / 8;
n = ((rand() % m) + 1) * 8;
assert (n <= sizeof(plain));
for (j = 0; j < n; j++)
plain[j] = rand() & 0xFF;
/* Encrypt it into ciphertext */
result = TDEA_Bytes(cipher, plain, n, key, ENCRYPT);
assert (result == 0);
/* Now decipher (use same variable) */
result = TDEA_Bytes(cipher, cipher, n, key, DECRYPT);
assert (result == 0);
/* Check identical */
assert (memcmp(plain, cipher, n) == 0);
printf("%d(%d) ", i+1, n);
}
printf("\n");
printf("...%s tested OK\n", testfn);
}
void test_TDEA_BytesMode_rand(void)
/* Encrypt and decrypt random blocks with random keys
in random modes
*/
{
char *testfn = "TDEA_BytesMode_rand()";
unsigned char key[24];
unsigned char plain[1024];
unsigned char cipher[1024];
unsigned char iv[8];
char *modes[] = { "ECB", "CBC" };
int i, j, n, m, im;
long result;
srand((unsigned)time(NULL));
printf("Testing %s...\n", testfn);
for (i = 0; i < 10; i++)
{
/* Create a random key and IV */
for (j = 0; j < 24; j++)
key[j] = rand() & 0xFF;
for (j = 0; j < 8; j++)
iv[j] = rand() & 0xFF;
/* Create some 'random' plaintext up to 1024 bytes long */
/* in a multiple of block size */
m = 1024 / 8;
n = ((rand() % m) + 1) * 8;
assert (n <= sizeof(plain));
for (j = 0; j < n; j++)
plain[j] = rand() & 0xFF;
/* Select a mode index: 0 or 1 */
im = rand() & 0x01;
/* Encrypt it into ciphertext */
result = TDEA_BytesMode(cipher, plain, n, key, ENCRYPT, modes[im], iv);
assert (result == 0);
/* Now decipher (use same variable) */
result = TDEA_BytesMode(cipher, cipher, n, key, DECRYPT, modes[im], iv);
assert (result == 0);
/* Check identical */
assert (memcmp(plain, cipher, n) == 0);
printf("%d(%d) ", i+1, n);
}
printf("\n");
printf("...%s tested OK\n", testfn);
}
/* HASH TESTS */
/* Correct message digest test vectors */
/* Hash('abc') */
#define OK_MD5_ABC "900150983cd24fb0d6963f7d28e17f72"
#define OK_MD2_ABC "da853b0d3f88d99b30283a69e6ded6bb"
#define OK_SHA1_ABC "a9993e364706816aba3e25717850c26c9cd0d89d"
#define OK_SHA224_ABC "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7"
#define OK_SHA256_ABC "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
#define OK_SHA384_ABC "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7"
#define OK_SHA512_ABC "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"
#define OK_RMD160_ABC "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc"
/* Hash(empty-string) */
#define OK_SHA1_EMPTY "da39a3ee5e6b4b0d3255bfef95601890afd80709"
#define OK_SHA512_EMPTY "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"
void test_HASH_HexFromHex(void)
{
char *testfn = "HASH_HexFromHex()";
long result;
char szDigest[API_MAX_HASH_CHARS+1]; /* NB extra one for terminating null character */
char *szMsgHex = "616263"; /* = "abc" */
printf("Testing %s...\n", testfn);
/* Compute default SHA-1 digest */
result = HASH_HexFromHex(szDigest, sizeof(szDigest)-1, szMsgHex, 0);
assert(result > 0);
printf("SHA1('abc')=%s\n", szDigest);
assert(strcmp(szDigest, OK_SHA1_ABC) == 0);
/* Compute MD5 digest */
result = HASH_HexFromHex(szDigest, sizeof(szDigest)-1, szMsgHex, API_HASH_MD5);
assert(result > 0);
printf("MD5('abc')=%s\n", szDigest);
assert(strcmp(szDigest, OK_MD5_ABC) == 0);
/* Compute MD2 digest */
result = HASH_HexFromHex(szDigest, sizeof(szDigest)-1, szMsgHex, API_HASH_MD2);
assert(result > 0);
printf("MD2('abc')=%s\n", szDigest);
assert(strcmp(szDigest, OK_MD2_ABC) == 0);
/* Compute SHA-224 digest */
result = HASH_HexFromHex(szDigest, sizeof(szDigest)-1, szMsgHex, API_HASH_SHA224);
assert(result > 0);
printf("SHA224('abc')=%s\n", szDigest);
assert(strcmp(szDigest, OK_SHA224_ABC) == 0);
/* Compute SHA-256 digest */
result = HASH_HexFromHex(szDigest, sizeof(szDigest)-1, szMsgHex, API_HASH_SHA256);
assert(result > 0);
printf("SHA256('abc')=%s\n", szDigest);
assert(strcmp(szDigest, OK_SHA256_ABC) == 0);
/* Compute SHA-384 digest */
result = HASH_HexFromHex(szDigest, sizeof(szDigest)-1, szMsgHex, API_HASH_SHA384);
assert(result > 0);
printf("SHA384('abc')=%s\n", szDigest);
assert(strcmp(szDigest, OK_SHA384_ABC) == 0);
/* Compute SHA-512 digest */
result = HASH_HexFromHex(szDigest, sizeof(szDigest)-1, szMsgHex, API_HASH_SHA512);
assert(result > 0);
printf("SHA512('abc')=%s\n", szDigest);
assert(strcmp(szDigest, OK_SHA512_ABC) == 0);
/* Compute RIPEMD-160 digest */
result = HASH_HexFromHex(szDigest, sizeof(szDigest)-1, szMsgHex, API_HASH_RMD160);
assert(result > 0);
printf("RMD160('abc')=%s\n", szDigest);
assert(strcmp(szDigest, OK_RMD160_ABC) == 0);
/* Compute digest of empty string */
result = HASH_HexFromHex(szDigest, sizeof(szDigest)-1, "", API_HASH_SHA1);
assert(result > 0);
printf("SHA1(e)=%s\n", szDigest);
assert(strcmp(szDigest, OK_SHA1_EMPTY) == 0);
result = HASH_HexFromHex(szDigest, sizeof(szDigest)-1, "", API_HASH_SHA512);
assert(result > 0);
printf("SHA512(e)=%s\n", szDigest);
assert(strcmp(szDigest, OK_SHA512_EMPTY) == 0);
printf("...%s tested OK\n", testfn);
}
void test_SHA1_StringHexHash(void)
{
long result;
char sDigest[41]; /* NB 1 extra char */
char sCorrect[] = "a9993e364706816aba3e25717850c26c9cd0d89d";
printf("Testing SHA1_StringHexHash()...\n");
result = SHA1_StringHexHash(sDigest, "abc");
assert (result == 0);
printf("Result =%s\n", sDigest);
printf("Correct=%s\n", sCorrect);
assert (strcmp(sDigest, sCorrect) == 0);
printf("...SHA1_StringHexHash() tested OK\n");
}
void test_SHA2_StringHexHash(void)
{
char *testfn = "SHA2_StringHexHash()";
long result;
char sDigest[65]; /* NB 1 extra char */
char sCorrect[] =
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad";
printf("Testing %s...\n", testfn);
result = SHA2_StringHexHash(sDigest, "abc");
assert (result == 0);
printf("Result =%s\n", sDigest);
printf("Correct=%s\n", sCorrect);
assert (strcmp(sDigest, sCorrect) == 0);
printf("...%s tested OK\n", testfn);
}
void test_MD5_StringHexHash(void)
{
long result;
char sDigest[33]; /* NB 1 extra char */
char sCorrect[] = "900150983cd24fb0d6963f7d28e17f72";
printf("Testing MD5_StringHexHash()...\n");
result = MD5_StringHexHash(sDigest, "abc");
assert (result == 0);
printf("Result =%s\n", sDigest);
printf("Correct=%s\n", sCorrect);
assert (strcmp(sDigest, sCorrect) == 0);
printf("...MD5_StringHexHash() tested OK\n");
}
void test_SHA1_BytesHexHash(void)
{
char *testfn = "SHA1_BytesHexHash()";
long result;
char sDigest[41]; /* NB 1 extra char */
char sCorrect[] = "a9993e364706816aba3e25717850c26c9cd0d89d";
unsigned char bytes[3];
printf("Testing %s...\n", testfn);
bytes[0] = 'a';
bytes[1] = 'b';
bytes[2] = 'c';
result = SHA1_BytesHexHash(sDigest, bytes, 3);
assert (result == 0);
printf("Result =%s\n", sDigest);
printf("Correct=%s\n", sCorrect);
assert (strcmp(sDigest, sCorrect) == 0);
printf("...%s tested OK\n", testfn);
}
void test_SHA2_BytesHexHash(void)
{
char *testfn = "SHA2_BytesHexHash()";
long result;
char sDigest[65]; /* NB 1 extra char */
char sCorrect[] =
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad";
unsigned char bytes[3];
printf("Testing %s...\n", testfn);
bytes[0] = 'a';
bytes[1] = 'b';
bytes[2] = 'c';
result = SHA2_BytesHexHash(sDigest, bytes, 3);
assert (result == 0);
printf("Result =%s\n", sDigest);
printf("Correct=%s\n", sCorrect);
assert (strcmp(sDigest, sCorrect) == 0);
printf("...%s tested OK\n", testfn);
}
void test_MD5_BytesHexHash(void)
{
char *testfn = "MD5_BytesHexHash()";
long result;
char sDigest[33]; /* NB 1 extra char */
char sCorrect[] = "900150983cd24fb0d6963f7d28e17f72";
unsigned char bytes[3];
printf("Testing %s...\n", testfn);
bytes[0] = 'a';
bytes[1] = 'b';
bytes[2] = 'c';
result = MD5_BytesHexHash(sDigest, bytes, 3);
assert (result == 0);
printf("Result =%s\n", sDigest);
printf("Correct=%s\n", sCorrect);
assert (strcmp(sDigest, sCorrect) == 0);
printf("...%s tested OK\n", testfn);
}
void test_SHA1_BytesHash(void)
{
char *testfn = "SHA1_BytesHash()";
long result;
unsigned char digest[20]; /* NB minimum 20 bytes for SHA1 */
unsigned char correct[] = {
0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a, 0xba, 0x3e,
0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c, 0x9c, 0xd0, 0xd8, 0x9d
};
unsigned char bytes[3];
printf("Testing %s...\n", testfn);
bytes[0] = 'a';
bytes[1] = 'b';
bytes[2] = 'c';
result = SHA1_BytesHash(digest, bytes, 3);
assert (result == 0);
printf("Result =");
pr_hexbytes(digest, 20);
printf("Correct=");
pr_hexbytes(correct, 20);
assert (memcmp(digest, correct, 20) == 0);
printf("...%s tested OK\n", testfn);
}
void test_SHA2_BytesHash(void)
{
char *testfn = "SHA2_BytesHash()";
long result;
unsigned char digest[32]; /* NB minimum 32 bytes for SHA256 */
unsigned char correct[] = {
0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad
};
unsigned char bytes[3];
printf("Testing %s...\n", testfn);
bytes[0] = 'a';
bytes[1] = 'b';
bytes[2] = 'c';
result = SHA2_BytesHash(digest, bytes, 3);
assert (result == 0);
printf("Result =");
pr_hexbytes(digest, 32);
printf("Correct=");
pr_hexbytes(correct, 32);
assert (memcmp(digest, correct, 32) == 0);
printf("...%s tested OK\n", testfn);
}
void test_MD5_BytesHash(void)
{
char *testfn = "MD5_BytesHash()";
long result;
unsigned char digest[16]; /* NB minimum 16 bytes for MD5 */
unsigned char correct[] = {
0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0, 0xd6, 0x96,
0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72
};
unsigned char bytes[3];
printf("Testing %s...\n", testfn);
bytes[0] = 'a';
bytes[1] = 'b';
bytes[2] = 'c';
result = MD5_BytesHash(digest, bytes, 3);
assert (result == 0);
printf("Result =");
pr_hexbytes(digest, sizeof(digest));
printf("Correct=");
pr_hexbytes(correct, sizeof(digest));
assert (memcmp(digest, correct, sizeof(digest)) == 0);
printf("...%s tested OK\n", testfn);
}
void test_SHA1_HexDigest(void)
{
char *testfn = "SHA1_HexDigest()";
long result;
char sDigest[41]; /* NB 1 extra char */
char sCorrect[] = "a9993e364706816aba3e25717850c26c9cd0d89d";
long hContext;
unsigned char bytes[2];
printf("Testing %s...\n", testfn);
hContext = SHA1_Init();
assert (hContext != 0);
/* Combine _AddString and _AddBytes */
result = SHA1_AddString(hContext, "a");
assert (result == 0);
bytes[0] = 'b';
bytes[1] = 'c';
result = SHA1_AddBytes(hContext, bytes, 2);
assert (result == 0);
result = SHA1_HexDigest(sDigest, hContext);
assert (result == 0);
printf("Result =%s\n", sDigest);
printf("Correct=%s\n", sCorrect);
assert (strcmp(sDigest, sCorrect) == 0);
printf("...%s tested OK\n", testfn);
}
void test_SHA2_HexDigest(void)
{
char *testfn = "SHA2_HexDigest()";
long result;
char sDigest[65]; /* NB 1 extra char */
char sCorrect[] =
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad";
long hContext;
unsigned char bytes[2];
printf("Testing %s...\n", testfn);
hContext = SHA2_Init();
assert (hContext != 0);
/* Combine _AddString and _AddBytes */
result = SHA2_AddString(hContext, "a");
assert (result == 0);
bytes[0] = 'b';
bytes[1] = 'c';
result = SHA2_AddBytes(hContext, bytes, 2);
assert (result == 0);
result = SHA2_HexDigest(sDigest, hContext);
assert (result == 0);
printf("Result =%s\n", sDigest);
printf("Correct=%s\n", sCorrect);
assert (strcmp(sDigest, sCorrect) == 0);
printf("...%s tested OK\n", testfn);
}
void test_MD5_HexDigest(void)
{
char *testfn = "MD5_HexDigest()";
long result;
char sDigest[33]; /* NB 1 extra char */
char sCorrect[] = "900150983cd24fb0d6963f7d28e17f72";
long hContext;
unsigned char bytes[2];
printf("Testing %s...\n", testfn);
hContext = MD5_Init();
assert (hContext != 0);
/* Combine _AddString and _AddBytes */
result = MD5_AddString(hContext, "a");
assert (result == 0);
bytes[0] = 'b';
bytes[1] = 'c';
result = MD5_AddBytes(hContext, bytes, 2);
assert (result == 0);
result = MD5_HexDigest(sDigest, hContext);
assert (result == 0);
printf("Result =%s\n", sDigest);
printf("Correct=%s\n", sCorrect);
assert (strcmp(sDigest, sCorrect) == 0);
printf("...%s tested OK\n", testfn);
}
void test_SHA1_AddString(void)
{
char *testfn = "SHA1_AddString()";
long result;
char sDigest[41]; /* NB 1 extra char */
char sCorrect[] = "34aa973cd4c4daa4f61eeb2bdbad27316534016f";
long hContext;
char sA1000[1001];
int i;
printf("Testing %s...\n", testfn);
hContext = SHA1_Init();
assert (hContext != 0);
/* Create a string of 1000 'a's */
for (i = 0; i < 1000; i++)
sA1000[i] = 'a';
sA1000[i] = '\0';
/* Add 1000 times => one million repetitions of "a" */
for (i = 0; i < 1000; i++)
{
result = SHA1_AddString(hContext, sA1000);
assert (result == 0);
}
/* Create final digest */
result = SHA1_HexDigest(sDigest, hContext);
assert (result == 0);
printf("Result =%s\n", sDigest);
printf("Correct=%s\n", sCorrect);
assert (strcmp(sDigest, sCorrect) == 0);
printf("...%s tested OK\n", testfn);
}
void test_SHA2_AddString(void)
{
char *testfn = "SHA2_AddString()";
long result;
char sDigest[65]; /* NB 1 extra char */
char sCorrect[] =
"cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0";
long hContext;
char sA1000[1001];
int i;
printf("Testing %s...\n", testfn);
hContext = SHA2_Init();
assert (hContext != 0);
/* Create a string of 1000 'a's */
for (i = 0; i < 1000; i++)
sA1000[i] = 'a';
sA1000[i] = '\0';
/* Add 1000 times => one million repetitions of "a" */
for (i = 0; i < 1000; i++)
{
result = SHA2_AddString(hContext, sA1000);
assert (result == 0);
}
/* Create final digest */
result = SHA2_HexDigest(sDigest, hContext);
assert (result == 0);
printf("Result =%s\n", sDigest);
printf("Correct=%s\n", sCorrect);
assert (strcmp(sDigest, sCorrect) == 0);
printf("...%s tested OK\n", testfn);
}
void test_MD5_AddString(void)
{
char *testfn = "MD5_AddString()";
long result;
char sDigest[41]; /* NB 1 extra char */
char sCorrect[] = "7707d6ae4e027c70eea2a935c2296f21";
long hContext;
char sA1000[1001];
int i;
printf("Testing %s...\n", testfn);
hContext = MD5_Init();
assert (hContext != 0);
/* Create a string of 1000 'a's */
for (i = 0; i < 1000; i++)
sA1000[i] = 'a';
sA1000[i] = '\0';
/* Add 1000 times => one million repetitions of "a" */
for (i = 0; i < 1000; i++)
{
result = MD5_AddString(hContext, sA1000);
assert (result == 0);
}
/* Create final digest */
result = MD5_HexDigest(sDigest, hContext);
assert (result == 0);
printf("Result =%s\n", sDigest);
printf("Correct=%s\n", sCorrect);
assert (strcmp(sDigest, sCorrect) == 0);
printf("...%s tested OK\n", testfn);
}
void test_SHA1_Hmac_KAT(void)
{
char *testfn = "SHA1_Hmac_KAT()";
/* Example from Wei Dai's Crypto++ test vectors
fipstest.cpp - written and placed in the public domain by Wei Dai
*/
long result;
char sDigest[41]; /* NB 1 extra char */
char sCorrect[] = "0922d3405faa3d194f82a45830737d5cc6c75d24";
unsigned char key[] = {
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
0x40, 0x41, 0x42, 0x43,
};
char data[] = "Sample #2";
int key_len, data_len;
printf("Testing %s...\n", testfn);
/* From http://trolocsis.com/crypto++/fipstest_8cpp-source.html
MAC_KnownAnswerTest<HMAC<SHA> >(
"303132333435363738393a3b3c3d3e3f40414243",
"Sample #2",
"0922d3405faa3d194f82a45830737d5cc6c75d24");
*/
key_len = sizeof(key);
data_len = (long)strlen(data);
result = SHA1_Hmac(sDigest, (unsigned char*)data, data_len, key, key_len);
assert (result == 0);
printf("Result =%s\n", sDigest);
printf("Correct=%s\n", sCorrect);
assert (strcmp(sDigest, sCorrect) == 0);
printf("...%s tested OK\n", testfn);
}
void test_SHA2_Hmac_KAT(void)
{
char *testfn = "SHA2_Hmac_KAT()";
/* Example from Wei Dai's Crypto++ test vectors
fipstest.cpp - written and placed in the public domain by Wei Dai
*/
long result;
char sDigest[65]; /* NB 1 extra char */
char sCorrect[] =
"d28363f335b2dae468793a38680dea9f7fb8be1dceda197cdb3b1cb59a9f6422";
unsigned char key[] = {
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
0x40, 0x41, 0x42, 0x43,
};
char data[] = "abc";
int key_len, data_len;
printf("Testing %s...\n", testfn);
/* From http://trolocsis.com/crypto++/fipstest_8cpp-source.html
MAC_KnownAnswerTest<HMAC<SHA256> >(
"303132333435363738393a3b3c3d3e3f40414243",
"abc",
"D28363F335B2DAE468793A38680DEA9F7FB8BE1DCEDA197CDB3B1CB59A9F6422");
*/
key_len = sizeof(key);
data_len = (long)strlen(data);
result = SHA2_Hmac(sDigest, (unsigned char*)data, data_len, key, key_len);
assert (result == 0);
printf("Result =%s\n", sDigest);
printf("Correct=%s\n", sCorrect);
assert (strcmp(sDigest, sCorrect) == 0);
printf("...%s tested OK\n", testfn);
}
void test_MD5_Hmac(void)
{
char *testfn = "MD5_Hmac()";
long result;
char sDigest[33]; /* NB 1 extra char */
char sCorrect1[] = "9294727a3638bb1c13f48ef8158bfc9d";
char sCorrect2[] = "750c783e6ab0b503eaa86e310a5db738";
char sCorrect3[] = "56be34521d144c88dbb8c733f0e8b3f6";
int i;
unsigned char key1[16];
unsigned char key2[] = "Jefe";
unsigned char key3[16];
unsigned char data1[] = "Hi There";
unsigned char data2[] = "what do ya want for nothing?";
unsigned char data3[50];
int key_len, data_len;
printf("Testing %s...\n", testfn);
/* Test No 1. from RFC 2104
key = 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
key_len = 16 bytes
data = "Hi There"
data_len = 8 bytes
digest = 0x9294727a3638bb1c13f48ef8158bfc9d
*/
key_len = 16;
for (i = 0; i < key_len; i++)
key1[i] = 0x0b;
data_len = 8;
result = MD5_Hmac(sDigest, data1, data_len, key1, key_len);
assert (result == 0);
printf("Result =%s\n", sDigest);
printf("Correct=%s\n", sCorrect1);
assert (strcmp(sDigest, sCorrect1) == 0);
/* Test No 2.
key = "Jefe"
data = "what do ya want for nothing?"
data_len = 28 bytes
digest = 0x750c783e6ab0b503eaa86e310a5db738
*/
key_len = 4;
data_len = 28;
result = MD5_Hmac(sDigest, data2, data_len, key2, key_len);
assert (result == 0);
printf("Result =%s\n", sDigest);
printf("Correct=%s\n", sCorrect2);
assert (strcmp(sDigest, sCorrect2) == 0);
/* Test No 3.
key = 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
key_len 16 bytes
data = 0xDDDDDDDDDDDDDDDDDDDD...
..DDDDDDDDDDDDDDDDDDDD...
..DDDDDDDDDDDDDDDDDDDD...
..DDDDDDDDDDDDDDDDDDDD...
..DDDDDDDDDDDDDDDDDDDD
data_len = 50 bytes
digest = 0x56be34521d144c88dbb8c733f0e8b3f6
*/
key_len = 16;
for (i = 0; i < key_len; i++)
key3[i] = 0xAA;
data_len = 50;
for (i = 0; i < data_len; i++)
data3[i] = 0xDD;
result = MD5_Hmac(sDigest, data3, data_len, key3, key_len);
assert (result == 0);
printf("Result =%s\n", sDigest);
printf("Correct=%s\n", sCorrect3);
assert (strcmp(sDigest, sCorrect3) == 0);
printf("...%s tested OK\n", testfn);
}
void test_SHA1_FileHexHash(void)
/* 'hello' and 'bin' are filenames */
{
char *testfn = "SHA1_FileHexHash";
long result;
char sDigest[41]; /* NB 1 extra char */
char sCorrectT[] = "22596363b3de40b06f981fb85d82312e8c0ed511";
char sCorrectB[] = "88a5b867c3d110207786e66523cd1e4a484da697";
char sCorrectBIN[] = "dbe649daba340bce7a44b809016d914839b99f10";
char *hello = "hello$$.txt";
char *bin = "bin$$.dat";
printf("Testing %s...\n", testfn);
create_hello_file(hello);
create_bin_file(bin);
#ifndef unix
result = SHA1_FileHexHash(sDigest, hello, "t");
assert (result == 0);
printf("Result =%s\n", sDigest);
printf("Correct=%s\n", sCorrectT);
assert (strcmp(sDigest, sCorrectT) == 0);
#else
result = (long)sCorrectT[0]; /* fudge to avoid compiler warning */
#endif
result = SHA1_FileHexHash(sDigest, hello, "b");
assert (result == 0);
printf("Result =%s\n", sDigest);
printf("Correct=%s\n", sCorrectB);
assert (strcmp(sDigest, sCorrectB) == 0);
result = SHA1_FileHexHash(sDigest, bin, "b");
assert (result == 0);
printf("Result =%s\n", sDigest);
printf("Correct=%s\n", sCorrectBIN);
assert (strcmp(sDigest, sCorrectBIN) == 0);
remove(hello);
remove(bin);
printf("...%s tested OK\n", testfn);
/*
C:\Test>sha1sum hello.txt
22596363b3de40b06f981fb85d82312e8c0ed511 hello.txt
C:\Test>sha1sum -b hello.txt
88a5b867c3d110207786e66523cd1e4a484da697 *hello.txt
C:\Test>sha1sum -b test.bin
dbe649daba340bce7a44b809016d914839b99f10 *test.bin
*/
}
void test_SHA2_FileHexHash(void)
{
char *testfn = "SHA2_FileHexHash";
long result;
char sDigest[65]; /* NB 1 extra char */
char sCorrectT[] =
"a948904f2f0f479b8f8197694b30184b0d2ed1c1cd2a1ec0fb85d299a192a447";
char sCorrectB[] =
"572a95fee9c0f320030789e4883707affe12482fbb1ea04b3ea8267c87a890fb";
char sCorrectBIN[] =
"110009dcee21620b166f3abfecb5eff7a873be729d1c2d53822e7acc5f34eb9b";
char *hello = "hello$$2.txt";
char *bin = "bin$$2.dat";
printf("Testing %s...\n", testfn);
create_hello_file(hello);
create_bin_file(bin);
#ifndef unix
result = SHA2_FileHexHash(sDigest, hello, "t");
assert (result == 0);
printf("Result =%s\n", sDigest);
printf("Correct=%s\n", sCorrectT);
assert (strcmp(sDigest, sCorrectT) == 0);
#else
result = (long)sCorrectT[0]; /* fudge to avoid compiler warning */
#endif
result = SHA2_FileHexHash(sDigest, hello, "b");
assert (result == 0);
printf("Result =%s\n", sDigest);
printf("Correct=%s\n", sCorrectB);
assert (strcmp(sDigest, sCorrectB) == 0);
result = SHA2_FileHexHash(sDigest, bin, "b");
assert (result == 0);
printf("Result =%s\n", sDigest);
printf("Correct=%s\n", sCorrectBIN);
assert (strcmp(sDigest, sCorrectBIN) == 0);
remove(hello);
remove(bin);
printf("...%s tested OK\n", testfn);
}
void test_MD5_FileHexHash(void)
/* 'hello' and 'bin' are filenames */
{
char *testfn = "MD5_FileHexHash";
long result;
char sDigest[41]; /* NB 1 extra char */
char sCorrectT[] = "6f5902ac237024bdd0c176cb93063dc4";
char sCorrectB[] = "a0f2a3c1dcd5b1cac71bf0c03f2ff1bd";
char sCorrectBIN[] = "f5c8e3c31c044bae0e65569560b54332";
char *hello = "hello$$.txt";
char *bin = "bin$$.dat";
printf("Testing %s...\n", testfn);
create_hello_file(hello);
create_bin_file(bin);
#ifndef unix
result = MD5_FileHexHash(sDigest, hello, "t");
assert (result == 0);
printf("Result =%s\n", sDigest);
printf("Correct=%s\n", sCorrectT);
assert (strcmp(sDigest, sCorrectT) == 0);
#else
result = (long)sCorrectT[0]; /* fudge to avoid compiler warning */
#endif
result = MD5_FileHexHash(sDigest, hello, "b");
assert (result == 0);
printf("Result =%s\n", sDigest);
printf("Correct=%s\n", sCorrectB);
assert (strcmp(sDigest, sCorrectB) == 0);
result = MD5_FileHexHash(sDigest, bin, "b");
assert (result == 0);
printf("Result =%s\n", sDigest);
printf("Correct=%s\n", sCorrectBIN);
assert (strcmp(sDigest, sCorrectBIN) == 0);
remove(hello);
remove(bin);
printf("...%s tested OK\n", testfn);
/*
C:\Test>md5sum -t hello.txt
6f5902ac237024bdd0c176cb93063dc4 hello.txt
C:\Test>md5sum -b hello.txt
a0f2a3c1dcd5b1cac71bf0c03f2ff1bd *hello.txt
C:\Test>md5sum -b test.bin
f5c8e3c31c044bae0e65569560b54332 *test.bin
*/
}
void test_MAC_HexFromBytes(void)
{
char *testfn = "MAC_HexFromBytes()";
long result;
char szDigest[API_MAX_HASH_CHARS+1]; /* NB extra one for terminating null character */
/* Test Case 2 RFC 2202 and RFC 4231 */
char *key = "Jefe";
char *data = "what do ya want for nothing?";
printf("Testing %s...\n", testfn);
/* Compute default HMAC-SHA-1 */
result = MAC_HexFromBytes(szDigest, sizeof(szDigest)-1,
(unsigned char*)data, (long)strlen(data), (unsigned char*)key, (long)strlen(key), 0);
assert(result > 0);
printf("HMAC-SHA-1('Jefe', WDYWFN?)=%s\n", szDigest);
assert(strcmp(szDigest, "effcdf6ae5eb2fa2d27416d5f184df9c259a7c79") == 0);
/* Compute HMAC-MD5 */
result = MAC_HexFromBytes(szDigest, sizeof(szDigest)-1,
(unsigned char*)data, (long)strlen(data), (unsigned char*)key, (long)strlen(key), API_HASH_MD5);
assert(result > 0);
printf("HMAC-MD5('Jefe', WDYWFN?)=%s\n", szDigest);
assert(strcmp(szDigest, "750c783e6ab0b503eaa86e310a5db738") == 0);
/* Compute HMAC-SHA-224 */
result = MAC_HexFromBytes(szDigest, sizeof(szDigest)-1,
(unsigned char*)data, (long)strlen(data), (unsigned char*)key, (long)strlen(key), API_HASH_SHA224);
assert(result > 0);
printf("HMAC-SHA-224('Jefe', WDYWFN?)=%s\n", szDigest);
assert(strcmp(szDigest,
"a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44") == 0);
/* Compute HMAC-SHA-256 */
result = MAC_HexFromBytes(szDigest, sizeof(szDigest)-1,
(unsigned char*)data, (long)strlen(data), (unsigned char*)key, (long)strlen(key), API_HASH_SHA256);
assert(result > 0);
printf("HMAC-SHA-256('Jefe', WDYWFN?)=%s\n", szDigest);
assert(strcmp(szDigest,
"5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843") == 0);
/* Compute HMAC-SHA-384 */
result = MAC_HexFromBytes(szDigest, sizeof(szDigest)-1,
(unsigned char*)data, (long)strlen(data), (unsigned char*)key, (long)strlen(key), API_HASH_SHA384);
assert(result > 0);
printf("HMAC-SHA-384('Jefe', WDYWFN?)=%s\n", szDigest);
assert(strcmp(szDigest,
"af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e8e2240ca5e69e2c78b3239ecfab21649") == 0);
/* Compute HMAC-SHA-512 */
result = MAC_HexFromBytes(szDigest, sizeof(szDigest)-1,
(unsigned char*)data, (long)strlen(data), (unsigned char*)key, (long)strlen(key), API_HASH_SHA512);
assert(result > 0);
printf("HMAC-SHA-512('Jefe', WDYWFN?)=%s\n", szDigest);
assert(strcmp(szDigest,
"164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737") == 0);
printf("...%s tested OK\n", testfn);
}
void test_CMAC_HexFromBytes(void)
{
char *testfn = "CMAC_HexFromBytes()";
long r;
char szOutput[API_MAX_CMAC_CHARS+1];
unsigned char *data;
long key_len, data_len;
unsigned char *key;
unsigned char key128[] = {
0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C,
};
unsigned char key3des[] = {
0x8A, 0xA8, 0x3B, 0xF8, 0xCB, 0xDA, 0x10, 0x62,
0x0B, 0xC1, 0xBF, 0x19, 0xFB, 0xB6, 0xCD, 0x58,
0xBC, 0x31, 0x3D, 0x4A, 0x37, 0x1C, 0xA8, 0xB5,
};
unsigned char M1[] = {
0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96,
0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A,
};
printf("Testing %s...\n", testfn);
key = key128;
key_len = sizeof(key128);
/* Test 1. */
data = M1;
data_len = sizeof(M1);
/* Check required size */
r = MAC_HexFromBytes(NULL, 0, data, data_len, key, key_len, API_CMAC_AES128);
printf("MAC_HexFromBytes(NULL, 0,..,AES) returns %ld\n", r);
assert(r > 0);
r = MAC_HexFromBytes(szOutput, sizeof(szOutput)-1, data, data_len, key, key_len, API_CMAC_AES128);
assert(r > 0);
printf("CMAC-AES-128(Ex1)=%s\n", szOutput);
assert(strcmp(szOutput, "070a16b46b4d4144f79bdd9dd04a287c") == 0);
/* Compute CMAC-DES-EDE */
key = key3des;
key_len = sizeof(key3des);
/* Test 0 = empty string */
data = NULL;
data_len = 0;
/* Check required size */
r = MAC_HexFromBytes(NULL, 0, data, data_len, key, key_len, API_CMAC_TDEA);
printf("MAC_HexFromBytes(NULL, 0,..,TDEA) returns %ld\n", r);
assert(r > 0);
r = MAC_HexFromBytes(szOutput, sizeof(szOutput)-1, data, data_len, key, key_len, API_CMAC_DESEDE);
assert(r > 0);
printf("CMAC-DES-EDE(<empty>)=%s\n", szOutput);
assert(strcmp(szOutput, "b7a688e122ffaf95") == 0);
printf("...%s tested OK\n", testfn);
}
void test_CMAC_HexFromHex(void)
{
char *testfn = "CMAC_HexFromHex()";
long r;
char szDigest[API_MAX_CMAC_CHARS+1]; /* NB extra one for terminating null character */
/* SP800-38B D.1 AES-128 */
char *szKeyHex = "2b7e151628aed2a6abf7158809cf4f3c";
char *szMsgHex = "6bc1bee22e409f96e93d7e117393172a";
char *lpszOK;
printf("Testing %s...\n", testfn);
/* Compute CMAC_AES-128 on empty string */
r = MAC_HexFromHex(szDigest, sizeof(szDigest)-1, "", szKeyHex, API_CMAC_AES128);
assert(r > 0);
printf("CMAC-AES-128(K128, e)=%s\n", szDigest);
lpszOK = "bb1d6929e95937287fa37d129b756746";
assert(strcmp(szDigest, lpszOK) == 0);
/* Compute CMAC_AES-128 on Example 2: Mlen = 128 */
r = MAC_HexFromHex(szDigest, sizeof(szDigest)-1, szMsgHex, szKeyHex, API_CMAC_AES128);
assert(r > 0);
printf("CMAC-AES-128(K128, M128)=%s\n", szDigest);
lpszOK = "070a16b46b4d4144f79bdd9dd04a287c";
assert(strcmp(szDigest, lpszOK) == 0);
/* CMAC_AES-256 on Example 12: Mlen = 512 */
szKeyHex = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4";
szMsgHex = "6bc1bee22e409f96e93d7e117393172a"
"ae2d8a571e03ac9c9eb76fac45af8e51"
"30c81c46a35ce411e5fbc1191a0a52ef"
"f69f2445df4f9b17ad2b417be66c3710";
r = MAC_HexFromHex(szDigest, sizeof(szDigest)-1, szMsgHex, szKeyHex, API_CMAC_AES256);
assert(r > 0);
printf("CMAC-AES-256(K256, M512)=%s\n", szDigest);
lpszOK = "e1992190549f6ed5696a2c056c315410";
assert(strcmp(szDigest, lpszOK) == 0);
/* CMAC_TDEA on Example 16: Mlen = 256 */
szKeyHex = "8aa83bf8cbda10620bc1bf19fbb6cd58bc313d4a371ca8b5";
szMsgHex = "6bc1bee22e409f96e93d7e117393172a"
"ae2d8a571e03ac9c9eb76fac45af8e51";
r = MAC_HexFromHex(szDigest, sizeof(szDigest)-1, szMsgHex, szKeyHex, API_CMAC_DESEDE);
assert(r > 0);
printf("CMAC-DES-EDE(K192, M256)=%s\n", szDigest);
lpszOK = "33e6b1092400eae5";
assert(strcmp(szDigest, lpszOK) == 0);
printf("Test with invalid parameters...\n");
/* CMAC_AES-128 on an invalid hex string */
r = MAC_HexFromHex(szDigest, sizeof(szDigest)-1, "A", szKeyHex, API_CMAC_AES128);
printf("CMAC-AES-128(key, 0xA) returns %ld (expected -ve error)\n\t%s\n", r, lookup_error(r));
assert(r < 0);
/* CMAC_DES_EDE on an invalid key */
r = MAC_HexFromHex(szDigest, sizeof(szDigest)-1, szMsgHex, "", API_CMAC_DESEDE);
printf("CMAC-DES_EDE(BADKEY, M) returns %ld (expected -ve error)\n\t%s\n", r, lookup_error(r));
assert(r < 0);
printf("...%s tested OK\n", testfn);
}
void test_PBE_Kdf2(void)
{
char *testfn = "PBE_Kdf2()";
/* Use des-ede3-cbc example from test vectors by
Dr. Stephen Henson using PBKDF2 defined in PKCS #5 v2.0.
*/
unsigned char dk[24];
char pwd[] = "password";
unsigned char salt[] = { 0x78, 0x57, 0x8E, 0x5A, 0x5D, 0x63, 0xCB, 0x06 };
long dkLen, pwdLen, saltLen, count;
long result;
unsigned char correct[] = {
0xBF, 0xDE, 0x6B, 0xE9, 0x4D, 0xF7, 0xE1, 0x1D, 0xD4, 0x09, 0xBC, 0xE2,
0x0A, 0x02, 0x55, 0xEC, 0x32, 0x7C, 0xB9, 0x36, 0xFF, 0xE9, 0x36, 0x43
};
printf("Testing %s...\n", testfn);
// Compute the derived key DK given the password, salt and iteration count
dkLen = sizeof(dk);
pwdLen = (long)strlen(pwd);
saltLen = sizeof(salt);
count = 2048;
result = PBE_Kdf2(dk, dkLen, (unsigned char*)pwd, pwdLen, salt, saltLen, count, 0);
assert (result == 0);
assert (result == 0);
printf("Result =");
pr_hexbytes(dk, dkLen);
printf("Correct=");
pr_hexbytes(correct, dkLen);
assert (memcmp(dk, correct, dkLen) == 0);
printf("...%s tested OK\n", testfn);
return;
}
void test_PBE_Kdf2_SHA2(void)
{
char *testfn = "PBE_Kdf2_SHA2()";
/* Same as above but uses SHA-2 hash functions in HMAC.
*/
long result;
char pwd[] = "password";
char *salthex = "78578e5a5d63cb06";
char *correcthex256 = "97B5A91D35AF542324881315C4F849E327C4707D1BC9D322";
char *correcthex224 = "10CFFEDFB13503519969151E466F587028E0720B387F9AEF";
char *pcorrecthex;
long count = 2048;
long dkLen = 24;
char dkhex[2*24+1] = { 0 };
printf("Testing %s...\n", testfn);
printf("Using HMAC-SHA-256...\n");
pcorrecthex = correcthex256;
result = PBE_Kdf2Hex(dkhex, sizeof(dkhex)-1, dkLen, pwd, salthex, count, API_HASH_SHA256);
printf("PBE_Kdf2Hex returns %ld\n", result);
assert(result == 0);
printf("Result =%s\n", dkhex);
printf("Correct=%s\n", pcorrecthex);
assert(strcmp(dkhex, pcorrecthex) == 0);
printf("Using HMAC-SHA-224...\n");
pcorrecthex = correcthex224;
result = PBE_Kdf2Hex(dkhex, sizeof(dkhex)-1, dkLen, pwd, salthex, count, API_HASH_SHA224);
printf("PBE_Kdf2Hex returns %ld\n", result);
assert(result == 0);
printf("Result =%s\n", dkhex);
printf("Correct=%s\n", pcorrecthex);
assert(strcmp(dkhex, pcorrecthex) == 0);
printf("...%s tested OK\n", testfn);
return;
}
void test_BLF_Hex(void)
{
long result;
char sInputHex[] = "0123456789ABCDEF";
char sKeyHex[] = "FEDCBA9876543210";
char sCorrectHex[] = "0ACEAB0FC6A0A28D";
/* NB Output for Hex requires an extra byte */
char sOutputHex[sizeof(sInputHex)+1];
printf("Testing BLF_Hex()...\n");
result = BLF_Hex(sOutputHex, sInputHex, sKeyHex, 1);
assert (result == 0);
printf("Result =%s\n", sOutputHex);
printf("Correct=%s\n", sCorrectHex);
assert (strcmp(sOutputHex, sCorrectHex) == 0);
printf("...BLF_Hex() tested OK\n");
}
void test_BLF_HexMode(void)
{
char *testfn = "BLF_HexMode()";
long lngRet;
// "7654321 Now is the time for " padded to 32 bytes with 4 nulls
char sInput[] = "37363534333231204E6F77206973207468652074696D6520666F722000000000";
char sCorrect[] = "6B77B4D63006DEE605B156E27403979358DEB9E7154616D959F1652BD5FF92CC";
char sHexKey[] = "0123456789ABCDEFF0E1D2C3B4A59687";
char sHexIV[] = "FEDCBA9876543210";
// Set sOutput to be same length as sInput
char sOutput[sizeof(sInput)+1];
printf("Testing %s...\n", testfn);
printf("KY=%s\n", sHexKey);
printf("IV=%s\n", sHexIV);
printf("PT=%s\n", sInput);
// Encrypt in one-off process
lngRet = BLF_HexMode(sOutput, sInput, sHexKey, ENCRYPT, "CBC", sHexIV);
assert (lngRet == 0);
printf("CT=%s %ld\n", sOutput, lngRet);
printf("OK=%s\n", sCorrect);
assert (strcmp(sOutput, sCorrect) == 0);
// Now decrypt back to plain text
lngRet = BLF_HexMode(sOutput, sOutput, sHexKey, DECRYPT, "cbc", sHexIV);
assert (lngRet == 0);
printf("P'=%s %ld\n", sOutput, lngRet);
assert (strcmp(sOutput, sInput) == 0);
printf("...%s tested OK\n", testfn);
}
void test_BLF_UpdateHex(void)
{
long hContext;
long result;
char sKey[] = "0123456789ABCDEF";
char sHexString[33];
char *correct;
printf("Testing BLF_UpdateHex() in ECB mode ...\n");
hContext = BLF_InitHex(sKey, 1, "ECB", NULL);
if (hContext == 0)
printf("BLF_InitError=%ld\n", BLF_InitError());
assert (hContext != 0);
/* First part: "Now is t" in hex (8 chars) */
strcpy(sHexString, "4e6f772069732074");
result = BLF_UpdateHex(hContext, sHexString);
assert (result == 0);
correct = "CB08E682C67E32E2";
printf("Result =%s\n", sHexString);
printf("Correct=%s\n", correct);
assert (strcmp(sHexString, correct) == 0);
/* Second part: "he time for all " in hex (16 chars) */
strcpy(sHexString, "68652074696d6520666f7220616c6c20");
result = BLF_UpdateHex(hContext, sHexString);
assert (result == 0);
correct = "8FCB010AC2CE9B1D9C4538762E33B52F";
printf("Result =%s\n", sHexString);
printf("Correct=%s\n", correct);
assert (strcmp(sHexString, correct) == 0);
result = BLF_Final(hContext);
assert (result == 0);
/* Now decrypt */
hContext = BLF_InitHex(sKey, 0, "ECB", NULL);
if (hContext == 0)
printf("BLF_InitError=%ld\n", BLF_InitError());
assert (hContext != 0);
strcpy(sHexString, "CB08E682C67E32E2");
result = BLF_UpdateHex(hContext, sHexString);
assert (result == 0);
correct = "4E6F772069732074";
printf("Result =%s\n", sHexString);
printf("Correct=%s\n", correct);
assert (strcmp(sHexString, correct) == 0);
strcpy(sHexString, "8FCB010AC2CE9B1D9C4538762E33B52F");
result = BLF_UpdateHex(hContext, sHexString);
assert (result == 0);
correct = "68652074696D6520666F7220616C6C20";
printf("Result =%s\n", sHexString);
printf("Correct=%s\n", correct);
assert (strcmp(sHexString, correct) == 0);
result = BLF_Final(hContext);
assert (result == 0);
printf("...BLF_UpdateHex() tested OK\n");
}
void test_BLF_Bytes_rand(void)
/* Encrypt and decrypt random blocks */
{
unsigned char key[8] = {
0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 };
unsigned char plain[512];
unsigned char cipher[512];
int i, j, n;
long result;
srand((unsigned)time(NULL));
printf("Testing BLF_Bytes() with random blocks ...\n");
for (i = 0; i < 10; i++)
{
/* Create some 'random' plaintext up to 512 bytes long */
n = ((rand() & 0x2F) + 1) * 8; /* in multiple of 8 */
assert (n <= 512);
for (j = 0; j < n; j++)
plain[j] = rand() & 0xFF;
/* Encrypt it into ciphertext */
result = BLF_Bytes(cipher, plain, n, key, 8, 1);
assert (result == 0);
/* Now decipher (use same variable) */
result = BLF_Bytes(cipher, cipher, n, key, 8, 0);
assert (result == 0);
/* Check identical */
assert (memcmp(plain, cipher, n) == 0);
printf("%d(%d) ", i+1, n);
}
printf("\n...BLF_Bytes() tested OK\n");
}
void test_BLF_BytesMode_rkeys(void)
/* Encrypt and decrypt with random keys */
{
unsigned char key[56];
/* NB we don't want the trailing NUL here! */
unsigned char plain[32] = "Now is the time for all good men";
unsigned char cipher[sizeof(plain)];
unsigned char iv[8];
int i, j, n;
long result;
srand((unsigned)time(NULL));
printf("Testing BLF_BytesMode() with random keys and IV ...\n");
for (i = 0; i < 10; i++)
{
/* Create some 'random' keys from 1 to 56 bytes long */
n = (rand() % 56) + 1;
for (j = 0; j < n; j++)
key[j] = rand() & 0xFF;
for (j = 0; j < 8; j++)
iv[j] = rand() & 0xFF;
/* Encrypt it into ciphertext in CBC mode */
result = BLF_BytesMode(cipher, plain, sizeof(plain), key, n, 1,
"CBC", iv);
assert (result == 0);
/* Now decipher (use same variable for result) */
result = BLF_BytesMode(cipher, cipher, sizeof(cipher), key, n, 0,
"CBC", iv);
assert (result == 0);
/* Check identical */
assert (memcmp(plain, cipher, sizeof(plain)) == 0);
printf("%d(%d) ", i+1, n);
}
printf("\n...BLF_BytesMode() tested OK\n");
}
void test_BLF_BytesMode_rmode(void)
/* Encrypt and decrypt random blocks and modes */
{
unsigned char key[8] = {
0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 };
unsigned char iv[8] = {
0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF };
unsigned char plain[512];
unsigned char cipher[512];
int i, j, n;
long result;
char *mode[] = { "ECB", "CBC", "CFB", "OFB" };
int m;
srand((unsigned)time(NULL));
printf("Testing BLF_BytesMode() with random modes ...\n");
for (i = 0; i < 10; i++)
{
/* Create some 'random' plaintext up to 512 bytes long */
n = ((rand() & 0x2F) + 1) * 8; /* in multiple of 8 */
assert (n <= 512);
for (j = 0; j < n; j++)
plain[j] = rand() & 0xFF;
/* And pick a random mode */
m = rand() & 0x3;
printf("%d-%s(%d) ", i+1, mode[m], n);
/* Encrypt it into ciphertext */
result = BLF_BytesMode(cipher, plain, n, key, 8, 1,
mode[m], iv);
assert (result == 0);
/* Now decipher (use same variable) */
result = BLF_BytesMode(cipher, cipher, n, key, 8, 0,
mode[m], iv);
assert (result == 0);
/* Check identical */
assert (memcmp(plain, cipher, n) == 0);
}
printf("\n...BLF_BytesMode() tested OK\n");
}
void test_BLF_File(void)
{
char sFileIn[] = "test$.txt";
char sFileOut[] = "test$.ecb";
char sFileChk[] = "test$.chk";
unsigned char key[8] = {
0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 };
unsigned char correct[] = {
0x1a, 0xa1, 0x51, 0xb7, 0x7a, 0x5a, 0x33, 0x5c,
0x4e, 0x7e, 0xdc, 0x84, 0xa3, 0x86, 0xdc, 0x96 };
long result;
FILE *fp;
char buf[128], *cp;
int c, n;
/* Create a test file in current dir */
fp = fopen(sFileIn, "wb");
assert(fp != NULL);
fprintf(fp, "hello world\r\n");
fclose(fp);
printf("Testing BLF_File()...\n");
/* Encrypt it and create output file */
result = BLF_File(sFileOut, sFileIn, key, sizeof(key), 1, "ECB", NULL);
assert (result == 0);
/* Read this ciphertext file to a buffer and see if correct */
fp = fopen(sFileOut, "rb");
assert (fp != NULL);
printf("Result =");
for (n = 0, cp = buf; (c = fgetc(fp)) != EOF && n < sizeof(buf); n++)
{
*cp++ = c;
printf("%02X", (unsigned char)c);
}
fclose(fp);
printf("\n");
printf("Correct=");
pr_hexbytes(correct, sizeof(correct));
assert (memcmp(buf, correct, n) == 0);
/* Now decrypt back to plaintext */
result = BLF_File(sFileChk, sFileOut, key, sizeof(key), 0, "ECB", NULL);
assert (result == 0);
/* and check we got the plaintext we started with */
assert (cmp_files(sFileChk, sFileIn) == 0);
/* Delete the test files */
remove(sFileIn);
remove(sFileOut);
remove(sFileChk);
printf("...BLF_File() tested OK\n");
}
void test_ZLIB(void)
{
char *testfn = "ZLIB_De/Inflate()";
char *input =
"hello, hello, hello. This is a 'hello world' message "
"for the world, repeat, for the world.";
unsigned char *pcomp, *pcheck;
long uncomp_len, comp_len, result;
printf("Testing %s...\n", testfn);
/* Find out compressed length of ascii input
NB don't use (long)strlen for binary data */
uncomp_len = (long)strlen(input);
printf("Input length = %ld bytes\n", uncomp_len);
comp_len = ZLIB_Deflate(NULL, 0, (unsigned char*)input, uncomp_len);
assert (comp_len > 0);
printf("Compressed length = %ld bytes\n", comp_len);
/* Alloc buffer storage */
pcomp = (unsigned char*)malloc(comp_len);
assert (pcomp != NULL);
/* Do compression */
result = ZLIB_Deflate(pcomp, comp_len, (unsigned char*)input, uncomp_len);
assert (result > 0);
/* Now uncompress and check */
pcheck = (unsigned char*)malloc(uncomp_len);
assert(pcheck != NULL);
result = ZLIB_Inflate(pcheck, uncomp_len, pcomp, comp_len);
assert (result > 0);
printf("Inflated length = %ld\n", result);
/* Do we have the same as we started with? */
assert (memcmp(pcheck, input, uncomp_len) == 0);
free(pcomp);
free(pcheck);
printf("...%s tested OK\n", testfn);
}
void test_RNG_KeyBytes(void)
{
char *testfn = "RNG_KeyBytes()";
unsigned char key[8], prevkey[8] = { 0 };
long result;
int i;
printf("Testing %s...\n", testfn);
/* Generate 3 random keys with no seed */
for (i = 0; i < 3; i++)
{
result = RNG_KeyBytes(key, sizeof(key), NULL, 0);
assert (result == 0);
pr_hexbytes(key, sizeof(key));
// Make sure NOT the same as last time
assert (memcmp(key, prevkey, sizeof(key)) != 0);
memcpy(prevkey, key, sizeof(key));
}
printf("...%s tested OK\n", testfn);
}
void test_RNG_KeyHex(void)
{
char *testfn = "RNG_KeyHex()";
char hexkey[17], prevhexkey[17] = "";
long result;
int i;
int nbytes;
printf("Testing %s...\n", testfn);
/* Generate 3 random keys with no seed */
nbytes = sizeof(hexkey) / 2 - 1;
for (i = 0; i < 3; i++)
{
/* Deliberately write too few or too many bytes */
result = RNG_KeyHex(hexkey, sizeof(hexkey), nbytes++, NULL, 0);
assert (result == 0);
printf("%s\n", hexkey);
// Make sure NOT the same as last time
assert (strcmp(hexkey, prevhexkey) != 0);
strcpy(prevhexkey, hexkey);
}
printf("...%s tested OK\n", testfn);
}
void test_RNG_NonceData(void)
{
char *testfn = "RNG_NonceData()";
long result;
unsigned char nonce[32];
char hex[33];
int i;
printf("Testing %s...\n", testfn);
/* Generate nonce bytes */
for (i = 0; i < 4; i++)
{
result = RNG_NonceData(nonce, sizeof(nonce));
assert (result == 0);
pr_hexbytes(nonce, sizeof(nonce));
}
/* And in hex - deliberately too long! */
for (i = 0; i < 4; i++)
{
result = RNG_NonceDataHex(hex, sizeof(hex)-1, sizeof(hex) /*!!*/);
assert (result == 0);
printf("%s\n", hex);
}
printf("...%s tested OK\n", testfn);
}
void test_RNG_Number(void)
/* NOTE: RNG_Number replaced RNG_Long in version 4.0 */
{
char *testfn = "RNG_Number()";
long mylong;
long mymin = 256;
long mymax = 0x0fffffff;
int i;
printf("Testing %s...\n", testfn);
/* Generate set of random longs */
for (i = 0; i < 8; i++)
{
mylong = RNG_Number(mymin, mymax);
printf("%08lx ", mylong);
assert (mylong > mymin || mylong > mymax);
}
printf("\n");
printf("...%s tested OK\n", testfn);
}
void test_RNG_Test(void)
{
char *testfn = "RNG_Test()";
long result;
char *filename = "RNGtest.txt";
printf("Testing %s...\n", testfn);
result = RNG_Test(filename);
assert (result == 0);
/* Now delete the file */
if (remove(filename) == 0)
printf("Deleted file `%s'\n", filename);
else
printf("ERROR: Unable to delete file `%s'\n", filename);
printf("...%s tested OK\n", testfn);
}
/* NEW AES FUNCTION TESTS */
void test_AES128_Hex(void)
{
char *testfn = "AES128_Hex()";
char sHexKey[] = "00000000000000000000000000000000";
char sInput[] = "80000000000000000000000000000000";
char sCorrect[] = "3AD78E726C1EC02B7EBFE92B23D9EC34";
char sOutput[sizeof(sInput)+1];
long lngRet;
printf("Testing %s...\n", testfn);
printf("KY=%s\n", sHexKey);
printf("PT=%s\n", sInput);
// Encrypt in one-off process
lngRet = AES128_HexMode(sOutput, sInput, sHexKey, ENCRYPT, "ECB", NULL);
assert (lngRet == 0);
/* Check */
printf("CT=%s %ld\n", sOutput, lngRet);
printf("OK=%s\n", sCorrect);
assert (strcmp(sCorrect, sOutput) == 0);
// Now decrypt back to plain text using same buffer
lngRet = AES128_HexMode(sOutput, sOutput, sHexKey, DECRYPT, "ECB", NULL);
assert (lngRet == 0);
printf("P'=%s %ld\n", sOutput, lngRet);
assert (strcmp(sInput, sOutput) == 0);
printf("...%s tested OK\n", testfn);
}
void test_AES128_HexMode(void)
{
char *testfn = "AES128_HexMode()";
long lngRet;
char sHexKey[] = "0123456789ABCDEFF0E1D2C3B4A59687";
char sHexIV[] = "FEDCBA9876543210FEDCBA9876543210";
// "Now is the time for all good men"
char sInput[] = "4E6F77206973207468652074696D6520666F7220616C6C20676F6F64206D656E";
char sCorrect[] = "C3153108A8DD340C0BCB1DFE8D25D2320EE0E66BD2BB4A313FB75C5638E9E177";
// Set sOutput to be same length as sInput
char sOutput[sizeof(sInput)+1];
printf("Testing %s...\n", testfn);
printf("KY=%s\n", sHexKey);
printf("IV=%s\n", sHexIV);
printf("PT=%s\n", sInput);
// Encrypt in one-off process
lngRet = AES128_HexMode(sOutput, sInput, sHexKey, ENCRYPT, "CBC", sHexIV);
assert (lngRet == 0);
printf("CT=%s %ld\n", sOutput, lngRet);
printf("OK=%s\n", sCorrect);
assert (strcmp(sOutput, sCorrect) == 0);
// Now decrypt back to plain text
lngRet = AES128_HexMode(sOutput, sOutput, sHexKey, DECRYPT, "cbc", sHexIV);
assert (lngRet == 0);
printf("P'=%s %ld\n", sOutput, lngRet);
assert (strcmp(sOutput, sInput) == 0);
printf("...%s tested OK\n", testfn);
}
void test_AES128_HexModeError(void)
{
char *testfn = "AES128_HexModeError()";
long lngRet;
char sHexKey[] = "0123456789ABCDEFF0E1D2C3B4A59687";
char sHexIV[] = "FEDCBA9876543210FEDCBA9876543210";
// "Now is the time for all good men"
char sInput[] = "4E6F77206973207468652074696D6520666F7220616C6C20676F6F64206D656E";
//char sCorrect[] = "C3153108A8DD340C0BCB1DFE8D25D2320EE0E66BD2BB4A313FB75C5638E9E177";
// Set sOutput to be same length as sInput
char sOutput[sizeof(sInput)+1];
char badhex[] = "THIS IS NOT HEX!";
printf("Testing %s...\n", testfn);
// lngRet = AES128_HexMode(sOutput, sInput, sHexKey, ENCRYPT, "CBC", sHexIV);
/* Call with null output */
lngRet = AES128_HexMode(NULL, sInput, sHexKey, ENCRYPT, "CBC", sHexIV);
printf("AES128_HexMode returns %ld (%s)\n", lngRet, lookup_error(lngRet));
assert (lngRet != 0);
/* Call with null input */
lngRet = AES128_HexMode(sOutput, NULL, sHexKey, ENCRYPT, "CBC", sHexIV);
printf("AES128_HexMode returns %ld (%s)\n", lngRet, lookup_error(lngRet));
assert (lngRet != 0);
/* Call with empty input */
lngRet = AES128_HexMode(sOutput, "", sHexKey, ENCRYPT, "CBC", sHexIV);
printf("AES128_HexMode returns %ld (%s)\n", lngRet, lookup_error(lngRet));
assert (lngRet != 0);
/* Call with invalid input */
lngRet = AES128_HexMode(sOutput, badhex, sHexKey, ENCRYPT, "CBC", sHexIV);
printf("AES128_HexMode returns %ld (%s)\n", lngRet, lookup_error(lngRet));
assert (lngRet != 0);
/* Call with null key */
lngRet = AES128_HexMode(sOutput, sInput, NULL, ENCRYPT, "CBC", sHexIV);
printf("AES128_HexMode returns %ld (%s)\n", lngRet, lookup_error(lngRet));
assert (lngRet != 0);
/* Call with empty key */
lngRet = AES128_HexMode(sOutput, sInput, "", ENCRYPT, "CBC", sHexIV);
printf("AES128_HexMode returns %ld (%s)\n", lngRet, lookup_error(lngRet));
assert (lngRet != 0);
/* Call with invalid key */
lngRet = AES128_HexMode(sOutput, sInput, badhex, ENCRYPT, "CBC", sHexIV);
printf("AES128_HexMode returns %ld (%s)\n", lngRet, lookup_error(lngRet));
assert (lngRet != 0);
/* Call with null mode */
lngRet = AES128_HexMode(sOutput, sInput, sHexKey, ENCRYPT, NULL, sHexIV);
printf("AES128_HexMode returns %ld (%s)\n", lngRet, lookup_error(lngRet));
assert (lngRet != 0);
/* Call with empty mode */
lngRet = AES128_HexMode(sOutput, sInput, sHexKey, ENCRYPT, "", sHexIV);
printf("AES128_HexMode returns %ld (%s)\n", lngRet, lookup_error(lngRet));
assert (lngRet != 0);
/* Call with invalid mode */
lngRet = AES128_HexMode(sOutput, sInput, sHexKey, ENCRYPT, "XBAD", sHexIV);
printf("AES128_HexMode returns %ld (%s)\n", lngRet, lookup_error(lngRet));
assert (lngRet != 0);
/* Call with null IV */
lngRet = AES128_HexMode(sOutput, sInput, sHexKey, ENCRYPT, "CBC", NULL);
printf("AES128_HexMode returns %ld (%s)\n", lngRet, lookup_error(lngRet));
assert (lngRet != 0);
/* Call with empty IV */
lngRet = AES128_HexMode(sOutput, sInput, sHexKey, ENCRYPT, "CBC", "");
printf("AES128_HexMode returns %ld (%s)\n", lngRet, lookup_error(lngRet));
assert (lngRet != 0);
/* Call with invalid IV */
lngRet = AES128_HexMode(sOutput, sInput, sHexKey, ENCRYPT, "CBC", badhex);
printf("AES128_HexMode returns %ld (%s)\n", lngRet, lookup_error(lngRet));
assert (lngRet != 0);
printf("...%s tested OK\n", testfn);
}
void test_AES128_HexMode_CBC(void)
{
char *testfn = "AES128_HexMode_CBC()";
long lngRet;
// NIST SP800-38a F.2.1 CBC-AES128.Encrypt
char sHexKey[] = "2b7e151628aed2a6abf7158809cf4f3c";
char sHexIV[] = "000102030405060708090a0b0c0d0e0f";
char sInput[] = "6BC1BEE22E409F96E93D7E117393172A";
char sCorrect[] = "7649ABAC8119B246CEE98E9B12E9197D";
// Set sOutput to be same length as sInput
char sOutput[sizeof(sInput)+1];
printf("Testing %s...\n", testfn);
printf("KY=%s\n", sHexKey);
printf("IV=%s\n", sHexIV);
printf("PT=%s\n", sInput);
// Encrypt in one-off process
lngRet = AES128_HexMode(sOutput, sInput, sHexKey, ENCRYPT, "CBC", sHexIV);
assert (lngRet == 0);
printf("CT=%s %ld\n", sOutput, lngRet);
printf("OK=%s\n", sCorrect);
assert (strcmp(sOutput, sCorrect) == 0);
// Now decrypt back to plain text
lngRet = AES128_HexMode(sOutput, sOutput, sHexKey, DECRYPT, "cbc", sHexIV);
assert (lngRet == 0);
printf("P'=%s %ld\n", sOutput, lngRet);
assert (strcmp(sOutput, sInput) == 0);
printf("...%s tested OK\n", testfn);
}
void test_AES128_BytesMode_CBC(void)
{
char *testfn = "AES128_BytesMode_CBC()";
long lngRet, nbytes;
// NIST SP800-38a F.2.1 CBC-AES128.Encrypt
unsigned char key[16], iv[16], input[16], output[16], correct[16];
convert_hex_to_bytes(key, sizeof(key), "2b7e151628aed2a6abf7158809cf4f3c");
convert_hex_to_bytes(iv, sizeof(iv), "000102030405060708090a0b0c0d0e0f");
nbytes = convert_hex_to_bytes(input, sizeof(input), "6BC1BEE22E409F96E93D7E117393172A");
convert_hex_to_bytes(correct, sizeof(correct), "7649ABAC8119B246CEE98E9B12E9197D");
printf("Testing %s...\n", testfn);
printf("KY="); pr_hexbytes(key, sizeof(key));
printf("IV="); pr_hexbytes(iv, sizeof(iv));
printf("PT="); pr_hexbytes(input, sizeof(input));
// Encrypt in one-off process
lngRet = AES128_BytesMode(output, input, nbytes, key, ENCRYPT, "CBC", iv);
assert (lngRet == 0);
printf("CT="); pr_hexbytes(output, sizeof(output));
printf("OK="); pr_hexbytes(correct, sizeof(correct));
assert (memcmp(output, correct, nbytes) == 0);
// Now decrypt back to plain text
lngRet = AES128_BytesMode(output, output, nbytes, key, DECRYPT, "cbc", iv);
assert (lngRet == 0);
printf("P'="); pr_hexbytes(output, sizeof(output));
assert (memcmp(output, input, nbytes) == 0);
printf("...%s tested OK\n", testfn);
}
void test_AES192_HexMode_CBC(void)
{
char *testfn = "AES192_HexMode_CBC()";
long lngRet;
// NIST SP800-38a F.2.3 CBC-AES192.Encrypt
char sHexKey[] = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
char sHexIV[] = "000102030405060708090a0b0c0d0e0f";
char sInput[] = "6BC1BEE22E409F96E93D7E117393172A";
char sCorrect[] = "4F021DB243BC633D7178183A9FA071E8";
// Set sOutput to be same length as sInput
char sOutput[sizeof(sInput)+1];
printf("Testing %s...\n", testfn);
printf("KY=%s\n", sHexKey);
printf("IV=%s\n", sHexIV);
printf("PT=%s\n", sInput);
// Encrypt in one-off process
lngRet = AES192_HexMode(sOutput, sInput, sHexKey, ENCRYPT, "CBC", sHexIV);
assert (lngRet == 0);
printf("CT=%s %ld\n", sOutput, lngRet);
printf("OK=%s\n", sCorrect);
assert (strcmp(sOutput, sCorrect) == 0);
// Now decrypt back to plain text
lngRet = AES192_HexMode(sOutput, sOutput, sHexKey, DECRYPT, "cbc", sHexIV);
assert (lngRet == 0);
printf("P'=%s %ld\n", sOutput, lngRet);
assert (strcmp(sOutput, sInput) == 0);
printf("...%s tested OK\n", testfn);
}
void test_AES256_HexMode_CBC(void)
{
char *testfn = "AES256_HexMode_CBC()";
long lngRet;
// NIST SP800-38a F.2.5 CBC-AES256.Encrypt
char sHexKey[] =
"603deb1015ca71be2b73aef0857d7781"
"1f352c073b6108d72d9810a30914dff4";
char sHexIV[] = "000102030405060708090a0b0c0d0e0f";
char sInput[] = "6BC1BEE22E409F96E93D7E117393172A";
char sCorrect[] = "F58C4C04D6E5F1BA779EABFB5F7BFBD6";
// Set sOutput to be same length as sInput
char sOutput[sizeof(sInput)+1];
printf("Testing %s...\n", testfn);
printf("KY=%s\n", sHexKey);
printf("IV=%s\n", sHexIV);
printf("PT=%s\n", sInput);
// Encrypt in one-off process
lngRet = AES256_HexMode(sOutput, sInput, sHexKey, ENCRYPT, "CBC", sHexIV);
assert (lngRet == 0);
printf("CT=%s %ld\n", sOutput, lngRet);
printf("OK=%s\n", sCorrect);
assert (strcmp(sOutput, sCorrect) == 0);
// Now decrypt back to plain text
lngRet = AES256_HexMode(sOutput, sOutput, sHexKey, DECRYPT, "cbc", sHexIV);
assert (lngRet == 0);
printf("P'=%s %ld\n", sOutput, lngRet);
assert (strcmp(sOutput, sInput) == 0);
printf("...%s tested OK\n", testfn);
}
void test_AES128_Hex_Monte(void)
{
int i;
long lngRet;
char sBlock[] = "00000000000000000000000000000000";
char sKey[] = "00000000000000000000000000000000";
char sCorrect[] = "C34C052CC0DA8D73451AFE5F03BE297F";
char *testfn = "AES128_Hex_Monte()";
printf("Testing %s...\n", testfn);
printf("AES Monte Carlo TECB Mode Encrypt:\n");
printf("KY=%s\n", sKey);
printf("PT=%s\n", sBlock);
// Do 10,000 times
for (i = 0; i < 10000; i++)
{
lngRet = AES128_HexMode(sBlock, sBlock, sKey, ENCRYPT, "ECB", "");
assert (lngRet == 0);
}
printf("CT=%s\n", sBlock);
printf("OK=%s\n", sCorrect);
assert (strcmp(sBlock, sCorrect) == 0);
printf("...%s tested OK\n", testfn);
}
void test_AES128_FileHex(void)
{
char *testfn = "AES128_FileHex()";
long lngRet;
// Construct full path names to files
char *strFileIn = "now.txt";
char *strFileOut = "aesnow.enc";
char *strFileChk = "aesnow.chk";
char sHexKey[] = "0123456789ABCDEFF0E1D2C3B4A59687";
char sCorrect[] =
"F0D1AD6F901FFFAE5572A6928DAB52B0"
"64B25C79F876730321E36DC01011ACCE"
"9C68DA6958A93ADFDECD9A1418D61EFD";
printf("Testing %s...\n", testfn);
create_nowis_file(strFileIn);
// Encrypt plaintext file to cipher (with padding)
// WARNING: output file is just clobbered
lngRet = AES128_FileHex(strFileOut, strFileIn, sHexKey, ENCRYPT, "ECB", 0);
assert (lngRet == 0);
// Check we got the correct ciphertext
assert (cmp_file_with_hex(strFileOut, sCorrect) == 0);
// Now decrypt it
lngRet = AES128_FileHex(strFileChk, strFileOut, sHexKey, DECRYPT, "ECB", 0);
assert (lngRet == 0);
/* and check we got the plaintext we started with */
assert (cmp_files(strFileChk, strFileIn) == 0);
remove(strFileIn);
remove(strFileOut);
remove(strFileChk);
printf("...%s tested OK\n", testfn);
}
void test_AESnnn_BytesMode_rand(void)
/* Encrypt and decrypt random blocks with random keys
and random modes */
{
char *testfn = "AESnnn_BytesMode_rand()";
unsigned char key[32];
unsigned char plain[1024];
unsigned char cipher[1024];
long keybits;
unsigned char iv[16];
char *modes[] = { "ECB", "CBC" };
int i, j, n, im;
long result;
srand((unsigned)time(NULL));
printf("Testing AESnnn_BytesMode() with random blocks and modes...\n");
for (i = 0; i < 10; i++)
{
/* Select a random key size: 128|192|256 */
keybits = ((rand() % 3) + 2) * 64;
/* Create a random key */
for (j = 0; j < keybits / 8; j++)
key[j] = rand() & 0xFF;
/* and a random IV */
for (j = 0; j < sizeof(iv); j++)
iv[j] = rand() & 0xFF;
/* Select a mode index: 0 or 1 */
im = rand() & 0x01;
/* Create some 'random' plaintext up to 1024 bytes long */
/* in a multiple of block size */
n = ((rand() % 16) + 1) * 16;
assert (n <= sizeof(plain));
for (j = 0; j < n; j++)
plain[j] = rand() & 0xFF;
printf("%d %ld-%s(%d) ", i+1, keybits, modes[im], n);
/* Encrypt it into ciphertext */
switch (keybits)
{
case 128:
result = AES128_BytesMode(cipher, plain, n, key, ENCRYPT, modes[im], iv);
break;
case 192:
result = AES192_BytesMode(cipher, plain, n, key, ENCRYPT, modes[im], iv);
break;
case 256:
result = AES256_BytesMode(cipher, plain, n, key, ENCRYPT, modes[im], iv);
break;
}
assert (result == 0);
/* Now decipher (use same variable) */
switch (keybits)
{
case 128:
result = AES128_BytesMode(cipher, cipher, n, key, DECRYPT, modes[im], iv);
break;
case 192:
result = AES192_BytesMode(cipher, cipher, n, key, DECRYPT, modes[im], iv);
break;
case 256:
result = AES256_BytesMode(cipher, cipher, n, key, DECRYPT, modes[im], iv);
break;
}
assert (result == 0);
/* Check identical */
//printf("KY="); pr_hexbytes(key, keybits / 8);
//if (im > 0) { printf("IV="); pr_hexbytes(iv, sizeof(iv)); }
//printf("PT="); pr_hexbytes(plain, n);
//printf("P'="); pr_hexbytes(cipher, n);
assert (memcmp(plain, cipher, n) == 0);
}
printf("...%s tested OK\n", testfn);
}
void test_AESnnn_InitUpdate_rand(void)
/* Encrypt and decrypt random blocks with random keys
and random modes and random direction (encrypt/decrypt first) */
{
char *testfn = "AESnnn_InitUpdate_rand()";
unsigned char key[32];
unsigned char plain[1024];
unsigned char block[1024];
long keybits;
unsigned char iv[16];
char *modes[] = { "ECB", "CBC" };
int i, j, n, m, im;
long result;
long hContext;
int dir;
srand((unsigned)time(NULL));
printf("Testing AESnnn_InitUpdate_rand() with random blocks and modes...\n");
for (i = 0; i < 10; i++)
{
/* Select a random key size: 128|192|256 */
keybits = ((rand() % 3) + 2) * 64;
/* Create a random key */
for (j = 0; j < keybits / 8; j++)
key[j] = rand() & 0xFF;
/* and a random IV */
for (j = 0; j < sizeof(iv); j++)
iv[j] = rand() & 0xFF;
/* Select a mode index: 0 or 1 */
im = rand() & 0x01;
/* select a direction to encrypt or decrypt first */
dir = rand() & 0x01;
/* Create some 'random' plaintext up to 1024 bytes long */
/* in a multiple of block size */
n = ((rand() % 16) + 1) * 16;
assert (n <= sizeof(plain));
for (j = 0; j < n; j++)
plain[j] = rand() & 0xFF;
printf("%d %ld-%s-%s(%d) ", i+1, keybits, modes[im], (dir ? "ENCRYPT" : "DECRYPT"), n);
/* Initialise the AESnnn context */
switch (keybits)
{
case 128:
hContext = AES128_Init(key, dir, modes[im], iv);
break;
case 192:
hContext = AES192_Init(key, dir, modes[im], iv);
break;
case 256:
hContext = AES256_Init(key, dir, modes[im], iv);
break;
}
assert (hContext != 0); /* Context should not be zero */
/* Encrypt it into ciphertext in two parts */
m = rand() % n;
m = (m / 16) * 16;
memcpy(block, plain, n);
switch (keybits)
{
case 128:
result = AES128_Update(hContext, block, m);
result = AES128_Update(hContext, &block[m], n-m);
break;
case 192:
result = AES192_Update(hContext, block, m);
result = AES192_Update(hContext, &block[m], n-m);
break;
case 256:
result = AES256_Update(hContext, block, m);
result = AES256_Update(hContext, &block[m], n-m);
break;
}
assert (result == 0);
/* Now decipher (use same variable) */
switch (keybits)
{
case 128:
result = AES128_BytesMode(block, block, n, key, !dir, modes[im], iv);
break;
case 192:
result = AES192_BytesMode(block, block, n, key, !dir, modes[im], iv);
break;
case 256:
result = AES256_BytesMode(block, block, n, key, !dir, modes[im], iv);
break;
}
assert (result == 0);
/* Check identical */
//printf("KY="); pr_hexbytes(key, keybits / 8);
//if (im > 0) { printf("IV="); pr_hexbytes(iv, sizeof(iv)); }
//printf("PT="); pr_hexbytes(plain, n);
//printf("P'="); pr_hexbytes(block, n);
assert (memcmp(plain, block, n) == 0);
}
printf("...%s tested OK\n", testfn);
}
int test_PC1(void)
{
long result;
unsigned char key[] = {
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef
};
unsigned char input[] = {
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef
};
unsigned char output[sizeof(input)];
unsigned char correct[] = {
0x75, 0xb7, 0x87, 0x80, 0x99, 0xe0, 0xc5, 0x96
};
FILE *fp;
char *infile = "testpc1.dat";
char *outfile = "testpc1.enc";
char *chkfile = "testpc1.chk";
unsigned char buf[512];
unsigned char correctfile[] = {
0x75, 0x95, 0xc3, 0xe6, 0x11, 0x4a, 0x09, 0x78
};
printf("Testing PC1_Bytes ... \n");
printf("Key: ");
pr_hexbytes(key, sizeof(key));
printf("Input: ");
pr_hexbytes(input, sizeof(input));
/* Encrypt with PC1 */
result = PC1_Bytes(output, input, sizeof(input), key, sizeof(key));
printf("%ld Output: ", result);
pr_hexbytes(output, sizeof(output));
assert (result == 0);
assert (memcmp(output, correct, sizeof(correct)) == 0);
/* Now decrypt - i.e. just do it again */
result = PC1_Bytes(output, output, sizeof(output), key, sizeof(key));
printf("%ld Input: ", result);
pr_hexbytes(output, sizeof(output));
assert (result == 0);
assert (memcmp(output, input, sizeof(input)) == 0);
printf("... passed OK\n");
printf("Testing PC1_File ... \n");
/* Create a file of 512 0x01 bytes */
fp = fopen(infile, "wb");
assert (fp != NULL);
memset(buf, 0x01, 512);
fwrite(buf, 1, 512, fp);
fclose(fp);
printf("File PT: ");
pr_hexbytes(buf, sizeof(correctfile));
/* encrypt it with same key as before */
result = PC1_File(outfile, infile, key, sizeof(key));
assert (result == 0);
/* get first few bytes and compare with correct answer */
fp = fopen(outfile, "rb");
assert (fp != NULL);
fread(buf, 1, sizeof(correctfile), fp);
fclose(fp);
printf("File CT: ");
pr_hexbytes(buf, sizeof(correctfile));
printf("Correct: ");
pr_hexbytes(correctfile, sizeof(correctfile));
/* Now decrypt by doing it again */
result = PC1_File(chkfile, outfile, key, sizeof(key));
assert (result == 0);
assert (cmp_files(chkfile, infile) == 0);
printf("... passed OK\n");
/* Clean up */
remove(infile);
remove(outfile);
remove(chkfile);
return 0;
}
/* CRC FUNCTIONS */
void test_CRC_Bytes(void)
{
char *testfn = "CRC_Bytes()";
char *msg = "123456789";
long crc;
printf("Testing %s...\n", testfn);
crc = CRC_Bytes((unsigned char*)msg, (long)strlen(msg), 0);
printf("CRC32(\"%s\")=%08lx\n", msg, crc);
assert (crc == 0xCBF43926);
printf("...%s tested OK\n", testfn);
}
void test_CRC_String(void)
{
char *testfn = "CRC_String()";
char *msg = "123456789";
char *hello = "hello world\x0d\x0a";
long crc;
printf("Testing %s...\n", testfn);
crc = CRC_String(msg, 0);
printf("CRC32(\"%s\")=%08lx\n", msg, crc);
assert (crc == 0xCBF43926);
crc = CRC_String(hello, 0);
printf("CRC32(\"%s\")=%08lx\n", hello, crc);
assert (crc == 0x38e6c41a);
printf("...%s tested OK\n", testfn);
}
void test_CRC_File(void)
{
char *testfn = "CRC_File()";
char *fname = "hello.txt";
long crc;
printf("Testing %s...\n", testfn);
/* Create a test file */
create_hello_file(fname);
crc = CRC_File(fname, 0);
printf("CRC32('%s')=%08lx\n", fname, crc);
assert (crc == 0x38e6c41a);
remove(fname);
printf("...%s tested OK\n", testfn);
}
/* WIPE FUNCTIONS */
void test_WIPE_Data(void)
{
char *testfn = "WIPE_Data()";
long ret;
char data[] = "123456789";
printf("Testing %s...\n", testfn);
printf("Before WIPE_Data=[%s]\n", data);
ret = WIPE_Data(data, (long)strlen(data));
printf("After WIPE_Data=[%s]\n", data);
assert (ret == 0);
printf("...%s tested OK\n", testfn);
}
void test_WIPE_File(void)
{
char *testfn = "WIPE_File()";
long ret;
char *fname = "tobewiped.dat";
printf("Testing %s...\n", testfn);
create_hello_file(fname);
printf("Before WIPE_File=[%s]\n", (file_exists(fname) ? "File exists" : "File not there"));
ret = WIPE_File(fname, 0);
printf("WIPE_File returns %ld\n", ret);
printf("After WIPE_File=[%s]\n", (file_exists(fname) ? "File exists" : "File not there"));
assert (ret == 0);
printf("...%s tested OK\n", testfn);
}
/* HEX ENCODING FUNCTIONS */
void test_CNV_BytesFromHexStr(void)
{
char *testfn = "CNV_BytesFromHexStr()";
char *hexdata = "FEDCBA9876543210";
long nbytes, nchars;
unsigned char *bp;
char *cp;
printf("Testing %s...\n", testfn);
printf("Hexdata %s -> ", hexdata);
nbytes = CNV_BytesFromHexStr(NULL, 0, hexdata);
printf("up to %ld bytes\n", nbytes);
assert(nbytes > 0);
bp = malloc(nbytes);
assert(bp != NULL);
nbytes = CNV_BytesFromHexStr(bp, nbytes, hexdata);
assert(nbytes == 8);
printf("...actually %ld bytes\n", nbytes);
pr_hexbytes(bp, nbytes);
// Now convert back to hex
nchars = CNV_HexStrFromBytes(NULL, 0, bp, nbytes);
printf("%ld hex chars\n", nchars);
assert(nchars > 0);
// NB allocate one extra for terminating null
cp = malloc(nchars + 1);
assert(cp != NULL);
nchars = CNV_HexStrFromBytes(cp, nchars, bp, nbytes);
assert(nchars == 16);
printf("Converts back to '%s' (%ld chars)\n", cp, nchars);
assert(strcmp(cp, hexdata) == 0);
free(bp);
free(cp);
printf("...%s tested OK\n", testfn);
}
void test_CNV_HexFilter(void)
{
char *testfn = "CNV_HexFilter()";
char badhexdata[] = " FE DC BA \n 98 \x00 76\r\n54321 0 ";
char goodhexdata[] = "fedcba9876543210";
char after[sizeof(badhexdata)];
long nchars;
printf("Testing %s...\n", testfn);
nchars = sizeof(badhexdata) - 1;
printf("Filtering a string of %ld chars...\n", nchars);
nchars = CNV_HexFilter(after, badhexdata, nchars);
printf("...returned %ld chars: %s\n", nchars, after);
assert (nchars == 16);
nchars = (long)strlen(goodhexdata);
printf("Filtering a string of %ld chars...\n", nchars);
nchars = CNV_HexFilter(after, goodhexdata, nchars);
printf("...returned %ld chars: %s\n", nchars, after);
assert (nchars == 16);
printf("...%s tested OK\n", testfn);
}
/* KEY WRAP FUNCTIONS */
void test_CIPHER_KeyWrap(void)
{
char *testfn = "CIPHER_KeyWrap()";
unsigned char kek_aes[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
};
unsigned char kdata_aes[] = {
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
};
unsigned char kdata_tdea[] = {
0x29, 0x23, 0xBF, 0x85, 0xE0, 0x6D, 0xD6, 0xAE,
0x52, 0x91, 0x49, 0xF1, 0xF1, 0xBA, 0xE9, 0xEA,
0xB3, 0xA7, 0xDA, 0x3D, 0x86, 0x0D, 0x3E, 0x98,
};
unsigned char kek_tdea[] = {
0x25, 0x5E, 0x0D, 0x1C, 0x07, 0xB6, 0x46, 0xDF,
0xB3, 0x13, 0x4C, 0xC8, 0x43, 0xBA, 0x8A, 0xA7,
0x1F, 0x02, 0x5B, 0x7C, 0x08, 0x38, 0x25, 0x1F,
};
unsigned char ok_128aes128[] = {
0x1F, 0xA6, 0x8B, 0x0A, 0x81, 0x12, 0xB4, 0x47,
0xAE, 0xF3, 0x4B, 0xD8, 0xFB, 0x5A, 0x7B, 0x82,
0x9D, 0x3E, 0x86, 0x23, 0x71, 0xD2, 0xCF, 0xE5,
};
unsigned char ok_256aes256[] = {
0x28, 0xC9, 0xF4, 0x04, 0xC4, 0xB8, 0x10, 0xF4,
0xCB, 0xCC, 0xB3, 0x5C, 0xFB, 0x87, 0xF8, 0x26,
0x3F, 0x57, 0x86, 0xE2, 0xD8, 0x0E, 0xD3, 0x26,
0xCB, 0xC7, 0xF0, 0xE7, 0x1A, 0x99, 0xF4, 0x3B,
0xFB, 0x98, 0x8B, 0x9B, 0x7A, 0x02, 0xDD, 0x21,
};
unsigned char cdata[sizeof(kdata_aes) + 16] = { 0 };
unsigned char check[sizeof(kdata_aes) + 16] = { 0 };
unsigned char *pkek, *pkdata, *pbok;
unsigned keklen, kdlen, cdlen, oklen;
int nlen;
printf("Testing %s...\n", testfn);
pkek = kek_aes;
pkdata = kdata_aes;
/* 4.1 Wrap 128 bits of Key Data with a 128-bit KEK */
printf("4.1 Wrap 128 bits of Key Data with a 128-bit KEK\n");
pbok = ok_128aes128;
oklen = sizeof(ok_128aes128);
keklen = 16;
kdlen = 16;
cdlen = kdlen + 8;
pr_bytesmsg("KEK =", pkek, keklen);
pr_bytesmsg("KeyData=", pkdata, kdlen);
nlen = CIPHER_KeyWrap(cdata, cdlen, pkdata, kdlen, pkek, keklen, API_BC_AES128);
printf("CIPHER_KeyWrap returns %d\n", nlen);
if (nlen > 0) pr_bytesmsg("Cipher =", cdata, nlen);
assert(nlen > 0);
pr_bytesmsg("OK =", pbok, oklen);
assert (memcmp(cdata, pbok, cdlen) == 0);
nlen = CIPHER_KeyUnwrap(check, sizeof(check), cdata, cdlen, pkek, keklen, API_BC_AES128);
printf("CIPHER_KeyUnwrap returns %d\n", nlen);
if (nlen > 0) pr_bytesmsg("KeyMat =", check, nlen);
assert(nlen == (long)kdlen);
assert(memcmp(check, pkdata, kdlen) == 0);
pr_bytesmsg("OK =", pkdata, kdlen);
/* 4.6 Wrap 256 bits of Key Data with a 256-bit KEK */
printf("4.6 Wrap 256 bits of Key Data with a 256-bit KEK\n");
pbok = ok_256aes256;
oklen = sizeof(ok_256aes256);
keklen = 32;
kdlen = 32;
cdlen = kdlen + 8;
pr_bytesmsg("KEK =", pkek, keklen);
pr_bytesmsg("KeyData=", pkdata, kdlen);
nlen = CIPHER_KeyWrap(cdata, cdlen, pkdata, kdlen, pkek, keklen, API_BC_AES256);
printf("CIPHER_KeyWrap returns %d\n", nlen);
if (nlen > 0) pr_bytesmsg("Cipher =", cdata, nlen);
assert(nlen > 0);
pr_bytesmsg("OK =", pbok, oklen);
assert (memcmp(cdata, pbok, cdlen) == 0);
nlen = CIPHER_KeyUnwrap(check, sizeof(check), cdata, cdlen, pkek, keklen, API_BC_AES256);
printf("CIPHER_KeyUnwrap returns %d\n", nlen);
if (nlen > 0) pr_bytesmsg("KeyMat =", check, nlen);
assert(nlen == (long)kdlen);
assert(memcmp(check, pkdata, kdlen) == 0);
pr_bytesmsg("OK =", pkdata, kdlen);
/* RFC3217 3.4 Triple-DES Key Wrap Example */
printf("RFC3217 3.4 Triple-DES Key Wrap Example\n");
pkek = kek_tdea;
pkdata = kdata_tdea;
keklen = 24;
kdlen = 24;
cdlen = 40;
pr_bytesmsg("KEK =", pkek, keklen);
pr_bytesmsg("KeyData=", pkdata, kdlen);
nlen = CIPHER_KeyWrap(cdata, cdlen, pkdata, kdlen, pkek, keklen, API_BC_TDEA);
printf("CIPHER_KeyWrap returns %d\n", nlen);
if (nlen > 0) pr_bytesmsg("Cipher =", cdata, nlen);
assert(nlen > 0);
// we don't have an OK result because the random IV used
nlen = CIPHER_KeyUnwrap(check, sizeof(check), cdata, cdlen, pkek, keklen, API_BC_TDEA);
printf("CIPHER_KeyUnwrap returns %d\n", nlen);
if (nlen > 0) pr_bytesmsg("KeyMat =", check, nlen);
assert(nlen == (long)kdlen);
assert(memcmp(check, pkdata, kdlen) == 0);
pr_bytesmsg("OK =", pkdata, kdlen);
printf("...%s tested OK\n", testfn);
}
/* GCM AUTHENTICATED ENCRYPTION */
static int do_gcm_test(const char *title,
const unsigned char *key, long keylen,
const unsigned char *pt, long ptlen,
const unsigned char *iv, long ivlen,
const unsigned char *adata, long alen,
const unsigned char *ok_ct, long okctlen,
const unsigned char *ok_tag, long oktaglen
)
{ /* Generic test bed for GCM_Encrypt */
unsigned char tag[16];
unsigned char *ct;
unsigned char *p1;
long taglen, ctlen, p1len;
long r;
ctlen = ptlen;
p1len = ptlen;
taglen = sizeof(tag);
/* Provide output */
ct = malloc(ctlen);
assert(ct);
p1 = malloc(ptlen);
assert(p1);
printf("%s", title);
pr_hexdump("K =", key, keylen, "\n");
pr_hexdump("PT=", pt, ptlen, "\n");
pr_hexdump("A =", adata, alen, "\n");
pr_hexdump("IV=", iv, ivlen, "\n");
r = GCM_Encrypt(ct, ctlen, tag, taglen, pt, ptlen, key, keylen, iv, ivlen, adata, alen, 0);
pr_hexdump("CT=", ct, ctlen, "\n");
assert(memcmp(ct, ok_ct, okctlen) == 0);
pr_hexdump("T =", tag, taglen, "\n");
assert(memcmp(tag, ok_tag, oktaglen) == 0);
r = GCM_Decrypt(p1, p1len, ct, ctlen, key, keylen, iv, ivlen, adata, alen, tag, taglen, 0);
pr_hexdump("P'=", p1, p1len, "\n");
assert(memcmp(pt, p1, p1len) == 0);
free(ct);
free(p1);
return 0;
}
void test_GCM_Encrypt(void)
{
char *testfn = "GCM_Encrypt()";
const char *title = "Test case 6:\n";
unsigned char key[] = {
0xFE, 0xFF, 0xE9, 0x92, 0x86, 0x65, 0x73, 0x1C,
0x6D, 0x6A, 0x8F, 0x94, 0x67, 0x30, 0x83, 0x08,
};
unsigned char pt[] = {
0xD9, 0x31, 0x32, 0x25, 0xF8, 0x84, 0x06, 0xE5,
0xA5, 0x59, 0x09, 0xC5, 0xAF, 0xF5, 0x26, 0x9A,
0x86, 0xA7, 0xA9, 0x53, 0x15, 0x34, 0xF7, 0xDA,
0x2E, 0x4C, 0x30, 0x3D, 0x8A, 0x31, 0x8A, 0x72,
0x1C, 0x3C, 0x0C, 0x95, 0x95, 0x68, 0x09, 0x53,
0x2F, 0xCF, 0x0E, 0x24, 0x49, 0xA6, 0xB5, 0x25,
0xB1, 0x6A, 0xED, 0xF5, 0xAA, 0x0D, 0xE6, 0x57,
0xBA, 0x63, 0x7B, 0x39,
};
unsigned char adata[] = {
0xFE, 0xED, 0xFA, 0xCE, 0xDE, 0xAD, 0xBE, 0xEF,
0xFE, 0xED, 0xFA, 0xCE, 0xDE, 0xAD, 0xBE, 0xEF,
0xAB, 0xAD, 0xDA, 0xD2,
};
unsigned char iv[] = {
0x93, 0x13, 0x22, 0x5D, 0xF8, 0x84, 0x06, 0xE5,
0x55, 0x90, 0x9C, 0x5A, 0xFF, 0x52, 0x69, 0xAA,
0x6A, 0x7A, 0x95, 0x38, 0x53, 0x4F, 0x7D, 0xA1,
0xE4, 0xC3, 0x03, 0xD2, 0xA3, 0x18, 0xA7, 0x28,
0xC3, 0xC0, 0xC9, 0x51, 0x56, 0x80, 0x95, 0x39,
0xFC, 0xF0, 0xE2, 0x42, 0x9A, 0x6B, 0x52, 0x54,
0x16, 0xAE, 0xDB, 0xF5, 0xA0, 0xDE, 0x6A, 0x57,
0xA6, 0x37, 0xB3, 0x9B,
};
unsigned char ok_ct[] = {
0x8C, 0xE2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xB6,
0x03, 0xA0, 0x33, 0xAC, 0xA1, 0x3F, 0xB8, 0x94,
0xBE, 0x91, 0x12, 0xA5, 0xC3, 0xA2, 0x11, 0xA8,
0xBA, 0x26, 0x2A, 0x3C, 0xCA, 0x7E, 0x2C, 0xA7,
0x01, 0xE4, 0xA9, 0xA4, 0xFB, 0xA4, 0x3C, 0x90,
0xCC, 0xDC, 0xB2, 0x81, 0xD4, 0x8C, 0x7C, 0x6F,
0xD6, 0x28, 0x75, 0xD2, 0xAC, 0xA4, 0x17, 0x03,
0x4C, 0x34, 0xAE, 0xE5,
};
unsigned char ok_tag[] = {
0x61, 0x9C, 0xC5, 0xAE, 0xFF, 0xFE, 0x0B, 0xFA,
0x46, 0x2A, 0xF4, 0x3C, 0x16, 0x99, 0xD0, 0x50,
};
printf("Testing %s...\n", testfn);
do_gcm_test(title, key, sizeof(key), pt, sizeof(pt), iv, sizeof(iv), adata, sizeof(adata),
ok_ct, sizeof(ok_ct), ok_tag, sizeof(ok_tag));
printf("...%s tested OK\n", testfn);
}
void test_GCM_Decrypt(void)
{
char *testfn = "GCM_Decrypt()";
unsigned char key[16] = { 0 };
unsigned char pt[16] = { 0 };
unsigned char iv[12] = { 0 };
unsigned char ct[] = {
0x03, 0x88, 0xDA, 0xCE, 0x60, 0xB6, 0xA3, 0x92,
0xF3, 0x28, 0xC2, 0xB9, 0x71, 0xB2, 0xFE, 0x78,
};
unsigned char tag[] = {
0xAB, 0x6E, 0x47, 0xD4, 0x2C, 0xEC, 0x13, 0xBD,
0xF5, 0x3A, 0x67, 0xB2, 0x12, 0x57, 0xBD, 0xDF,
};
unsigned char p1[16] = { 0xfa };
unsigned char *adata = NULL;
long alen = 0;
long keylen = sizeof(key);
long ptlen = sizeof(pt);
long ivlen = sizeof(iv);
long taglen = sizeof(tag);
long ctlen = sizeof(ct);
long p1len = sizeof(p1);
long r;
printf("Testing %s...\n", testfn);
r = GCM_Decrypt(p1, p1len, ct, ctlen, key, keylen, iv, ivlen, adata, alen, tag, taglen, 0);
printf("GCM_Decrypt returns %ld\n", r);
pr_hexdump("P'=", p1, p1len, "\n");
assert(memcmp(pt, p1, ptlen) == 0);
printf("Now expect an error..\n");
memset(p1, 0xfa, p1len);
pr_hexdump("Correct tag =", tag, taglen, "\n");
tag[0] = ~tag[0];
pr_hexdump("Corrupted tag=", tag, taglen, "\n");
r = GCM_Decrypt(p1, p1len, ct, ctlen, key, keylen, iv, ivlen, adata, alen, tag, taglen, 0);
printf("GCM_Decrypt returns %ld: %s\n", r, lookup_error(r));
assert(r != 0);
pr_hexdump("P'=", p1, p1len, "\n");
printf("..end of deliberate errors.\n");
printf("...%s tested OK\n", testfn);
}
void test_GCM_GMAC(void)
{
char *testfn = "GCM_GMAC()";
/* Test case 13 - 256-bit key, GMAC only */
unsigned char key[32] = { 0 };
unsigned char iv[12] = { 0 };
unsigned char tag[16];
unsigned char ok_tag[] = {
0x53, 0x0F, 0x8A, 0xFB, 0xC7, 0x45, 0x36, 0xB9,
0xA9, 0x63, 0xB4, 0xF1, 0xC4, 0xCB, 0x73, 0x8B,
};
unsigned char *adata = NULL;
long alen = 0;
long keylen = sizeof(key);
long ivlen = sizeof(iv);
long taglen = sizeof(tag);
long oktaglen = sizeof(ok_tag);
long r;
printf("Testing %s...\n", testfn);
printf("Test case 13 = GMAC only, 256-bit key, empty message string.\n");
pr_hexdump("K =", key, keylen, "\n");
pr_hexdump("A =", adata, alen, "\n");
pr_hexdump("IV=", iv, ivlen, "\n");
r = GCM_Encrypt(NULL, 0, tag, taglen, NULL, 0, key, keylen, iv, ivlen, adata, alen, 0);
pr_hexdump("GMAC('')=", tag, taglen, "\n");
assert(memcmp(tag, ok_tag, oktaglen) == 0);
printf("...%s tested OK\n", testfn);
}
/* GENERAL FUNCTIONS */
void test_API_Version(void)
{
char *testfn = "API_Version()";
long lngRet;
char timestamp[256];
printf("Testing %s...\n", testfn);
lngRet = API_Version();
printf("API_Version returns %ld.\n", lngRet);
lngRet = API_CompileTime(timestamp, sizeof(timestamp)-1);
printf("Compiled [%s]\n", timestamp);
lngRet = API_LicenceType(0);
printf("Licence Type=%c\n", (char)lngRet);
printf("...%s tested OK\n", testfn);
}
void test_API_ModuleName(void)
{
char *testfn = "API_ModuleName()";
long lngRet, len;
char *buf;
printf("Testing %s...\n", testfn);
len = API_ModuleName(NULL, 0, 0);
assert (len > 0);
buf = malloc(len);
assert(buf);
lngRet = API_ModuleName(buf, len, 0);
assert(lngRet > 0);
printf("API_ModuleName=[%s]\n", buf);
free(buf);
printf("...%s tested OK\n", testfn);
}
void test_API_PowerUpTests(void)
{
char *testfn = "API_PowerUpTests()";
long lngRet;
printf("Testing %s...\n", testfn);
lngRet = API_PowerUpTests(0);
printf("API_PowerUpTests returns %ld\n", lngRet);
printf("...%s tested OK\n", testfn);
}
void test_API_ErrorLookup(void)
{
char *testfn = "test_API_ErrorLookup()";
long lngRet;
char errmsg[128];
int i;
printf("Testing %s...\n", testfn);
for (i = 0; i < 10000; i++)
{
lngRet = API_ErrorLookup(errmsg, sizeof(errmsg)-1, i);
if (lngRet > 0)
printf("%d = %s\n", i, errmsg);
}
printf("...%s tested OK\n", testfn);
}
void do_all_tests(void)
{
test_AES128_BytesMode_CBC();
test_AES128_FileHex();
test_AES128_Hex();
test_AES128_HexMode();
test_AES128_HexModeError();
test_AES128_HexMode_CBC();
test_AES128_Hex_Monte();
test_AES192_HexMode_CBC();
test_AES256_HexMode_CBC();
test_AESnnn_BytesMode_rand();
test_AESnnn_InitUpdate_rand();
test_API_ErrorLookup();
test_API_PowerUpTests();
test_BLF_BytesMode_rkeys();
test_BLF_BytesMode_rmode();
test_BLF_Bytes_rand();
test_BLF_File();
test_BLF_Hex();
test_BLF_HexMode();
test_BLF_UpdateHex();
test_CIPHER_KeyWrap();
test_CNV_BytesFromHexStr();
test_CNV_HexFilter();
test_CRC_Bytes();
test_CRC_File();
test_CRC_String();
test_DES_Bytes_rand();
test_DES_CheckKey();
test_DES_FileHex();
test_DES_Hex();
test_DES_HexMode();
test_DES_UpdateHex();
test_HASH_HexFromHex();
test_MAC_HexFromBytes();
test_CMAC_HexFromBytes();
test_CMAC_HexFromHex();
test_MD5_AddString();
test_MD5_BytesHash();
test_MD5_BytesHexHash();
test_MD5_FileHexHash();
test_MD5_HexDigest();
test_MD5_Hmac();
test_MD5_StringHexHash();
test_PBE_Kdf2();
test_PBE_Kdf2_SHA2();
test_RNG_KeyBytes();
test_RNG_KeyHex();
test_RNG_Number();
test_RNG_NonceData();
test_RNG_Test();
test_SHA1_AddString();
test_SHA1_BytesHash();
test_SHA1_BytesHexHash();
test_SHA1_FileHexHash();
test_SHA1_HexDigest();
test_SHA1_Hmac_KAT();
test_SHA1_StringHexHash();
test_SHA2_AddString();
test_SHA2_BytesHash();
test_SHA2_BytesHexHash();
test_SHA2_FileHexHash();
test_SHA2_HexDigest();
test_SHA2_Hmac_KAT();
test_SHA2_StringHexHash();
test_TDEA_BytesMode_rand();
test_TDEA_Bytes_rand();
test_TDEA_FileHex();
test_TDEA_Hex();
test_TDEA_HexMode();
test_WIPE_Data();
test_WIPE_File();
test_ZLIB();
test_GCM_Encrypt();
test_GCM_Decrypt();
test_GCM_GMAC();
/* Do these last so we can see which ver we are using */
test_API_Version();
test_API_ModuleName();
}
int main()
{
int c;
/* MSVC memory leak checking stuff */
#if _MSC_VER >= 1100
_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
_CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );
_CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT );
_CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE );
_CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDOUT );
_CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE );
_CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDOUT );
#endif
make_new_test_dir();
do_all_tests();
printf("Version=%ld\n", API_Version());
printf("\nAll done.\n");
/* Option to clean up */
printf("The directory '%s' has been created by this test program.\n"
"Do you want to remove this directory? Y/N: ", testdir);
c = getchar();
if (c == 'Y' || c == 'y')
remove_test_dir(testdir, old_cwd);
return 0;
}