/* 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 3.2 or later)
Copyright (C) 2001-6 DI Management Services Pty Limited. All rights reserved.
Last updated:
$Date: 2006-07-15 19:48:00 $
$Revision: 3.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
#include "diCryptoSys.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <assert.h>
// Compiler-specific explicit link to library
// This works in MSVC and Borland for LIB in same dir - you may need to do otherwise
#pragma comment(lib, ".\\diCryptoSys.lib")
/* 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, "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(char *file1, char *file2)
/* Compares two binary files: returns 0 if identical
or 1 if not identical or -1 if file error */
{
FILE *fp1, *fp2;
int c1, c2;
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;
}
while ((c1 = fgetc(fp1)) != EOF)
{
c2 = fgetc(fp2);
if (c2 == EOF)
{ /* File 2 is shorter than file 1 */
result = 1;
break;
}
if (c1 != c2)
{ /* Found a mis-match */
result = 1;
break;
}
}
if (feof(fp1))
{ /* Make sure file2 is same length */
if ((c2 = fgetc(fp2)) != EOF)
result = 1;
}
fclose(fp1);
fclose(fp2);
return result;
}
int cmp_file_with_hex(char *file, char *hex_ok)
/* Returns zero if file contains exactly the bytes in hex_ok */
{
unsigned char *correct, *fbuf, *cp;
int i, n, x, result;
FILE *fp;
char hex[3];
/* Convert correct hex string to bytes */
n = 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, "%x", &x);
correct[i] = 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 = 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;
}
static void pr_hexbytes(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 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 %d\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 %d\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 %d\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 %d\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 %d\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 %d\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 %d\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 %d\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 */
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,
};
unsigned 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 = strlen(data);
result = SHA1_Hmac(sDigest, 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,
};
unsigned 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 = strlen(data);
result = SHA2_Hmac(sDigest, 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);
#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);
#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);
#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_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];
unsigned 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 = strlen(pwd);
saltLen = sizeof(salt);
count = 2048;
result = PBE_Kdf2(dk, dkLen, 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_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 %d\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 %d\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++ =