diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b0eddc7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +aes_test +arcfour_test +base64_test +blowfish_test +des_test +md2_test +md5_test +rot-13_test +sha1_test +sha256_test +speck128128_test diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..94770c9 --- /dev/null +++ b/Makefile @@ -0,0 +1,156 @@ +#!/bin/make +# @(#)Makefile 1.2 04 May 1995 02:06:57 +# +# crypto-algorithms-master - Brad Conte's basic implementations of standard cryptography algorithms +# +# @(#) $Revision$ +# @(#) $Id$ +# @(#) $Source$ +# +# chongo (Landon Curt Noll, http://www.isthe.com/chongo/index.html) /\oo/\ +# +# Share and enjoy! :-) + +SHELL= /bin/bash +CC= cc +CFLAGS= -O3 -g3 -std=c99 -Wall -pedantic + +INSTALL= install +DESTDIR= /usr/global/bin + +TEST_TARGETS= aes_test arcfour_test base64_test blowfish_test des_test md2_test md5_test rot-13_test sha1_test sha256_test \ + speck128128_test +TARGETS= ${TEST_TARGETS} + +all: ${TARGETS} + +aes_test: aes_test.o aes.o + ${CC} ${CFLAGS} aes_test.o aes.o -o aes_test + +aes.o: aes.c aes.h + ${CC} ${CFLAGS} aes.c -c + +aes_test.o: aes_test.c aes.h + ${CC} ${CFLAGS} aes_test.c -c + +arcfour_test: arcfour_test.o arcfour.o + ${CC} ${CFLAGS} arcfour_test.o arcfour.o -o arcfour_test + +arcfour.o: arcfour.c arcfour.h + ${CC} ${CFLAGS} arcfour.c -c + +arcfour_test.o: arcfour_test.c arcfour.h + ${CC} ${CFLAGS} arcfour_test.c -c + +base64_test: base64_test.o base64.o + ${CC} ${CFLAGS} base64_test.o base64.o -o base64_test + +base64.o: base64.c base64.h + ${CC} ${CFLAGS} base64.c -c + +base64_test.o: base64_test.c base64.h + ${CC} ${CFLAGS} base64_test.c -c + +blowfish_test: blowfish_test.o blowfish.o + ${CC} ${CFLAGS} blowfish_test.o blowfish.o -o blowfish_test + +blowfish.o: blowfish.c blowfish.h + ${CC} ${CFLAGS} blowfish.c -c + +blowfish_test.o: blowfish_test.c blowfish.h + ${CC} ${CFLAGS} blowfish_test.c -c + +des_test: des_test.o des.o + ${CC} ${CFLAGS} des_test.o des.o -o des_test + +des.o: des.c des.h + ${CC} ${CFLAGS} des.c -c + +des_test.o: des_test.c des.h + ${CC} ${CFLAGS} des_test.c -c + +md2_test: md2_test.o md2.o + ${CC} ${CFLAGS} md2_test.o md2.o -o md2_test + +md2.o: md2.c md2.h + ${CC} ${CFLAGS} md2.c -c + +md2_test.o: md2_test.c md2.h + ${CC} ${CFLAGS} md2_test.c -c + +md5_test: md5_test.o md5.o + ${CC} ${CFLAGS} md5_test.o md5.o -o md5_test + +md5.o: md5.c md5.h + ${CC} ${CFLAGS} md5.c -c + +md5_test.o: md5_test.c md5.h + ${CC} ${CFLAGS} md5_test.c -c + +rot-13_test: rot-13_test.o rot-13.o + ${CC} ${CFLAGS} rot-13_test.o rot-13.o -o rot-13_test + +rot-13.o: rot-13.c rot-13.h + ${CC} ${CFLAGS} rot-13.c -c + +rot-13_test.o: rot-13_test.c rot-13.h + ${CC} ${CFLAGS} rot-13_test.c -c + +sha1_test: sha1_test.o sha1.o + ${CC} ${CFLAGS} sha1_test.o sha1.o -o sha1_test + +sha1.o: sha1.c sha1.h + ${CC} ${CFLAGS} sha1.c -c + +sha1_test.o: sha1_test.c sha1.h + ${CC} ${CFLAGS} sha1_test.c -c + +sha256_test: sha256_test.o sha256.o + ${CC} ${CFLAGS} sha256_test.o sha256.o -o sha256_test + +sha256.o: sha256.c sha256.h + ${CC} ${CFLAGS} sha256.c -c + +sha256_test.o: sha256_test.c sha256.h + ${CC} ${CFLAGS} sha256_test.c -c + +speck128128_test: speck128128_test.o speck128128.o + ${CC} ${CFLAGS} speck128128_test.o speck128128.o -o speck128128_test + +speck128128_test.o: speck128128_test.c speck128128.h + ${CC} ${CFLAGS} speck128128_test.c -c + +speck128128.o: speck128128.c speck128128.h + ${CC} ${CFLAGS} speck128128.c -c + +test: ${TEST_TARGETS} + @export last_error="0"; \ + for i in ${TEST_TARGETS}; do \ + echo running '=-=' $$i '=-='; \ + ./$$i; \ + status="$$?"; \ + if [ "$$status" != 0 ]; then \ + echo "WARNING: test $$i failed!!"; \ + last_error="$$status"; \ + fi; \ + done; \ + if [ "$$last_error" = 0 ]; then \ + echo "=-=-= All tests PASSED =-=-="; \ + else \ + echo "=-=-= Some tests FAILED =-=-="; \ + fi; \ + exit "$$last_error" + +configure: + @echo nothing to configure + +clean quick_clean: + rm -f *.o + +clobber quick_clobber quick_distclean distclean: + rm -f *.o + rm -f ${TARGETS} + +install: all + @echo not configured to install, perhaps ${INSTALL} -m 0555 ${TARGETS} ${DESTDIR} + diff --git a/README.md b/README.md index 64eafd2..b2d15d3 100644 --- a/README.md +++ b/README.md @@ -14,4 +14,12 @@ These algorithms are not optimized for speed or space. They are primarily design Building --- -The source code for each algorithm will come in a pair of a source code file and a header file. There should be no inter-header file dependencies, no additional libraries, no platform-specific header files, or any other complicating matters. Compiling them should be as easy as adding the relevent source code to the project. \ No newline at end of file +The source code for each algorithm will come in a pair of a source code file and a header file. There should be no inter-header file dependencies, no additional libraries, no platform-specific header files, or any other complicating matters. Compiling them should be as easy as adding the relevent source code to the project. + +For systems have make: + +make clobber all + +To run all of the test: + +make test diff --git a/aes.h b/aes.h index 25721c8..d1ccf3b 100644 --- a/aes.h +++ b/aes.h @@ -11,13 +11,17 @@ /*************************** HEADER FILES ***************************/ #include +#include /****************************** MACROS ******************************/ #define AES_BLOCK_SIZE 16 // AES operates on 16 bytes at a time /**************************** DATA TYPES ****************************/ -typedef unsigned char BYTE; // 8-bit byte -typedef unsigned int WORD; // 32-bit word, change to "long" for 16-bit machines +#if !defined(CRYPTO_TYPES) +typedef uint8_t BYTE; // 8-bit byte +typedef uint32_t WORD; // 32-bit word, change to "long" for 16-bit machines +#define CRYPTO_TYPES +#endif /*********************** FUNCTION DECLARATIONS **********************/ /////////////////// diff --git a/aes_test.c b/aes_test.c index b8da963..c671fc5 100644 --- a/aes_test.c +++ b/aes_test.c @@ -15,8 +15,11 @@ /*************************** HEADER FILES ***************************/ #include #include +#include #include "aes.h" +extern int aes_decrypt_cbc(const BYTE in[], size_t in_len, BYTE out[], const WORD key[], int keysize, const BYTE iv[]); + /*********************** FUNCTION DEFINITIONS ***********************/ void print_hex(BYTE str[], int len) { @@ -279,7 +282,10 @@ int aes_test() int main(int argc, char *argv[]) { - printf("AES Tests: %s\n", aes_test() ? "SUCCEEDED" : "FAILED"); + int ret; // 0 ==> test failed, != 0 ==> test suceeded + + ret = aes_test(); + printf("AES Tests: %s\n", ret ? "SUCCEEDED" : "FAILED"); - return(0); + exit(ret == 0 ? 1 : 0); } diff --git a/arcfour.c b/arcfour.c index 37a88e1..d1ded06 100644 --- a/arcfour.c +++ b/arcfour.c @@ -26,17 +26,20 @@ void arcfour_key_setup(BYTE state[], const BYTE key[], int len) state[i] = state[j]; state[j] = t; } + state[ARCFOUR_I] = 0; + state[ARCFOUR_J] = 0; } -// This does not hold state between calls. It always generates the -// stream starting from the first output byte. void arcfour_generate_stream(BYTE state[], BYTE out[], size_t len) { - int i, j; + int i; + int j; size_t idx; BYTE t; - for (idx = 0, i = 0, j = 0; idx < len; ++idx) { + i = state[ARCFOUR_I]; + j = state[ARCFOUR_J]; + for (idx = 0; idx < len; ++idx) { i = (i + 1) % 256; j = (j + state[i]) % 256; t = state[i]; @@ -44,4 +47,6 @@ void arcfour_generate_stream(BYTE state[], BYTE out[], size_t len) state[j] = t; out[idx] = state[(state[i] + state[j]) % 256]; } + state[ARCFOUR_I] = i; + state[ARCFOUR_J] = j; } diff --git a/arcfour.h b/arcfour.h index f9f1e87..059457e 100644 --- a/arcfour.h +++ b/arcfour.h @@ -11,9 +11,13 @@ /*************************** HEADER FILES ***************************/ #include +#include /**************************** DATA TYPES ****************************/ -typedef unsigned char BYTE; // 8-bit byte +#if !defined(CRYPTO_TYPES) +typedef uint8_t BYTE; // 8-bit byte +#define CRYPTO_TYPES +#endif /*********************** FUNCTION DECLARATIONS **********************/ // Input: state - the state used to generate the keystream @@ -27,4 +31,11 @@ void arcfour_key_setup(BYTE state[], const BYTE key[], int len); // len - number of bytes to generate void arcfour_generate_stream(BYTE state[], BYTE out[], size_t len); +#if !defined(ARCFOUR_I) +# define ARCFOUR_I (256) +#endif +#if !defined(ARCFOUR_J) +# define ARCFOUR_J (257) +#endif + #endif // ARCFOUR_H diff --git a/arcfour_test.c b/arcfour_test.c index 985f8a7..f9b8b00 100644 --- a/arcfour_test.c +++ b/arcfour_test.c @@ -14,12 +14,13 @@ /*************************** HEADER FILES ***************************/ #include #include +#include #include "arcfour.h" /*********************** FUNCTION DEFINITIONS ***********************/ int rc4_test() { - BYTE state[256]; + BYTE state[256+2]; BYTE key[3][10] = {{"Key"}, {"Wiki"}, {"Secret"}}; BYTE stream[3][10] = {{0xEB,0x9F,0x77,0x81,0xB7,0x34,0xCA,0x72,0xA7,0x19}, {0x60,0x44,0xdb,0x6d,0x41,0xb7}, @@ -31,7 +32,7 @@ int rc4_test() // Only test the output stream. Note that the state can be reused. for (idx = 0; idx < 3; idx++) { - arcfour_key_setup(state, key[idx], strlen(key[idx])); + arcfour_key_setup(state, key[idx], strlen((char *)key[idx])); arcfour_generate_stream(state, buf, stream_len[idx]); pass = pass && !memcmp(stream[idx], buf, stream_len[idx]); } @@ -41,7 +42,10 @@ int rc4_test() int main() { - printf("ARCFOUR tests: %s\n", rc4_test() ? "SUCCEEDED" : "FAILED"); + int ret; // 0 ==> test failed, != 0 ==> test suceeded - return(0); + ret = rc4_test(); + printf("ARCFOUR Tests: %s\n", ret ? "SUCCEEDED" : "FAILED"); + + exit(ret == 0 ? 1 : 0); } diff --git a/base64.c b/base64.c index 5e89808..478a0e0 100644 --- a/base64.c +++ b/base64.c @@ -87,7 +87,6 @@ size_t base64_encode(const BYTE in[], BYTE out[], size_t len, int newline_flag) size_t base64_decode(const BYTE in[], BYTE out[], size_t len) { - BYTE ch; size_t idx, idx2, blks, blk_ceiling, left_over; if (in[len - 1] == '=') diff --git a/base64.h b/base64.h index e35c6c7..602c12d 100644 --- a/base64.h +++ b/base64.h @@ -11,9 +11,13 @@ /*************************** HEADER FILES ***************************/ #include +#include /**************************** DATA TYPES ****************************/ -typedef unsigned char BYTE; // 8-bit byte +#if !defined(CRYPTO_TYPES) +typedef uint8_t BYTE; // 8-bit byte +#define CRYPTO_TYPES +#endif /*********************** FUNCTION DECLARATIONS **********************/ // Returns the size of the output. If called with out = NULL, will just return diff --git a/base64_test.c b/base64_test.c index c59cc98..a24c237 100644 --- a/base64_test.c +++ b/base64_test.c @@ -14,6 +14,7 @@ /*************************** HEADER FILES ***************************/ #include #include +#include #include "base64.h" /*********************** FUNCTION DEFINITIONS ***********************/ @@ -31,16 +32,17 @@ int base64_test() int idx; for (idx = 0; idx < 3; idx++) { - buf_len = base64_encode(text[idx], buf, strlen(text[idx]), 1); - pass = pass && ((buf_len == strlen(code[idx])) && - (buf_len == base64_encode(text[idx], NULL, strlen(text[idx]), 1))); - pass = pass && !strcmp(code[idx], buf); + memset(buf, 0, sizeof(buf)); + buf_len = base64_encode(text[idx], buf, strlen((const char *)text[idx]), 1); + pass = pass && ((buf_len == strlen((const char *)code[idx])) && + (buf_len == base64_encode(text[idx], NULL, strlen((const char *)text[idx]), 1))); + pass = pass && !strcmp((const char *)code[idx], (const char *)buf); memset(buf, 0, sizeof(buf)); - buf_len = base64_decode(code[idx], buf, strlen(code[idx])); - pass = pass && ((buf_len == strlen(text[idx])) && - (buf_len == base64_decode(code[idx], NULL, strlen(code[idx])))); - pass = pass && !strcmp(text[idx], buf); + buf_len = base64_decode(code[idx], buf, strlen((const char *)code[idx])); + pass = pass && ((buf_len == strlen((const char *)text[idx])) && + (buf_len == base64_decode(code[idx], NULL, strlen((const char *)code[idx])))); + pass = pass && !strcmp((const char *)text[idx], (const char *)buf); } return(pass); @@ -48,7 +50,10 @@ int base64_test() int main() { - printf("Base64 tests: %s\n", base64_test() ? "PASSED" : "FAILED"); + int ret; // 0 ==> test failed, != 0 ==> test suceeded + + ret = base64_test(); + printf("Base64 Tests: %s\n", ret ? "SUCCEEDED" : "FAILED"); - return 0; + exit(ret == 0 ? 1 : 0); } diff --git a/blowfish.h b/blowfish.h index d8e9d4a..e4cd0b8 100644 --- a/blowfish.h +++ b/blowfish.h @@ -11,13 +11,17 @@ /*************************** HEADER FILES ***************************/ #include +#include /****************************** MACROS ******************************/ #define BLOWFISH_BLOCK_SIZE 8 // Blowfish operates on 8 bytes at a time /**************************** DATA TYPES ****************************/ -typedef unsigned char BYTE; // 8-bit byte -typedef unsigned int WORD; // 32-bit word, change to "long" for 16-bit machines +#if !defined(CRYPTO_TYPES) +typedef uint8_t BYTE; // 8-bit byte +typedef uint32_t WORD; // 32-bit word, change to "long" for 16-bit machines +#define CRYPTO_TYPES +#endif typedef struct { WORD p[18]; diff --git a/blowfish_test.c b/blowfish_test.c index 0f0aa38..835e0d7 100644 --- a/blowfish_test.c +++ b/blowfish_test.c @@ -14,6 +14,7 @@ /*************************** HEADER FILES ***************************/ #include #include +#include #include "blowfish.h" /*********************** FUNCTION DEFINITIONS ***********************/ @@ -62,7 +63,10 @@ int blowfish_test() int main() { - printf("Blowfish tests: %s\n", blowfish_test() ? "SUCCEEDED" : "FAILED"); + int ret; // 0 ==> test failed, != 0 ==> test suceeded - return(0); + ret = blowfish_test(); + printf("Blowfish Tests: %s\n", ret ? "SUCCEEDED" : "FAILED"); + + exit(ret == 0 ? 1 : 0); } diff --git a/des.c b/des.c index d20db6f..12b44c6 100644 --- a/des.c +++ b/des.c @@ -250,14 +250,14 @@ void des_crypt(const BYTE in[], BYTE out[], const BYTE key[][6]) void three_des_key_setup(const BYTE key[], BYTE schedule[][16][6], DES_MODE mode) { if (mode == DES_ENCRYPT) { - des_key_setup(&key[0],schedule[0],mode); - des_key_setup(&key[8],schedule[1],!mode); - des_key_setup(&key[16],schedule[2],mode); + des_key_setup(&key[0],schedule[0], DES_ENCRYPT); + des_key_setup(&key[8],schedule[1], DES_DECRYPT); + des_key_setup(&key[16],schedule[2], DES_ENCRYPT); } else /*if (mode == DES_DECRYPT*/ { - des_key_setup(&key[16],schedule[0],mode); - des_key_setup(&key[8],schedule[1],!mode); - des_key_setup(&key[0],schedule[2],mode); + des_key_setup(&key[16],schedule[0], DES_DECRYPT); + des_key_setup(&key[8],schedule[1], DES_ENCRYPT); + des_key_setup(&key[0],schedule[2], DES_DECRYPT); } } diff --git a/des.h b/des.h index 1503772..3485237 100644 --- a/des.h +++ b/des.h @@ -10,17 +10,21 @@ *********************************************************************/ #ifndef DES_H -#define DESH +#define DES_H /*************************** HEADER FILES ***************************/ #include +#include /****************************** MACROS ******************************/ #define DES_BLOCK_SIZE 8 // DES operates on 8 bytes at a time /**************************** DATA TYPES ****************************/ -typedef unsigned char BYTE; // 8-bit byte -typedef unsigned int WORD; // 32-bit word, change to "long" for 16-bit machines +#if !defined(CRYPTO_TYPES) +typedef uint8_t BYTE; // 8-bit byte +typedef uint32_t WORD; // 32-bit word, change to "long" for 16-bit machines +#define CRYPTO_TYPES +#endif typedef enum { DES_ENCRYPT, diff --git a/des_test.c b/des_test.c index 3e46134..56c812f 100644 --- a/des_test.c +++ b/des_test.c @@ -14,6 +14,7 @@ /*************************** HEADER FILES ***************************/ #include #include +#include #include "des.h" /*********************** FUNCTION DEFINITIONS ***********************/ @@ -41,35 +42,35 @@ int des_test() int pass = 1; des_key_setup(key1, schedule, DES_ENCRYPT); - des_crypt(pt1, buf, schedule); + des_crypt(pt1, buf, (const BYTE (*)[6]) schedule); pass = pass && !memcmp(ct1, buf, DES_BLOCK_SIZE); des_key_setup(key1, schedule, DES_DECRYPT); - des_crypt(ct1, buf, schedule); + des_crypt(ct1, buf, (const BYTE (*)[6]) schedule); pass = pass && !memcmp(pt1, buf, DES_BLOCK_SIZE); des_key_setup(key2, schedule, DES_ENCRYPT); - des_crypt(pt2, buf, schedule); + des_crypt(pt2, buf, (const BYTE (*)[6]) schedule); pass = pass && !memcmp(ct2, buf, DES_BLOCK_SIZE); des_key_setup(key2, schedule, DES_DECRYPT); - des_crypt(ct2, buf, schedule); + des_crypt(ct2, buf, (const BYTE (*)[6]) schedule); pass = pass && !memcmp(pt2, buf, DES_BLOCK_SIZE); three_des_key_setup(three_key1, three_schedule, DES_ENCRYPT); - three_des_crypt(pt1, buf, three_schedule); + three_des_crypt(pt1, buf, (const BYTE (*)[16][6]) three_schedule); pass = pass && !memcmp(ct3, buf, DES_BLOCK_SIZE); three_des_key_setup(three_key1, three_schedule, DES_DECRYPT); - three_des_crypt(ct3, buf, three_schedule); + three_des_crypt(ct3, buf, (const BYTE (*)[16][6]) three_schedule); pass = pass && !memcmp(pt1, buf, DES_BLOCK_SIZE); three_des_key_setup(three_key2, three_schedule, DES_ENCRYPT); - three_des_crypt(pt3, buf, three_schedule); + three_des_crypt(pt3, buf, (const BYTE (*)[16][6]) three_schedule); pass = pass && !memcmp(ct4, buf, DES_BLOCK_SIZE); three_des_key_setup(three_key2, three_schedule, DES_DECRYPT); - three_des_crypt(ct4, buf, three_schedule); + three_des_crypt(ct4, buf, (const BYTE (*)[16][6]) three_schedule); pass = pass && !memcmp(pt3, buf, DES_BLOCK_SIZE); return(pass); @@ -77,7 +78,10 @@ int des_test() int main() { - printf("DES test: %s\n", des_test() ? "SUCCEEDED" : "FAILED"); + int ret; // 0 ==> test failed, != 0 ==> test suceeded - return(0); + ret = des_test(); + printf("DES Tests: %s\n", ret ? "SUCCEEDED" : "FAILED"); + + exit(ret == 0 ? 1 : 0); } diff --git a/md2.c b/md2.c index de6bb6b..b2a4e89 100644 --- a/md2.c +++ b/md2.c @@ -102,3 +102,12 @@ void md2_final(MD2_CTX *ctx, BYTE hash[]) memcpy(hash, ctx->state, MD2_BLOCK_SIZE); } + +void md2(BYTE hash[], BYTE data[], size_t len) +{ + MD2_CTX ctx; + + md2_init(&ctx); + md2_update(&ctx, data, len); + md2_final(&ctx,hash); +} diff --git a/md2.h b/md2.h index 97706af..b2cee9b 100644 --- a/md2.h +++ b/md2.h @@ -11,12 +11,16 @@ /*************************** HEADER FILES ***************************/ #include +#include /****************************** MACROS ******************************/ #define MD2_BLOCK_SIZE 16 /**************************** DATA TYPES ****************************/ -typedef unsigned char BYTE; // 8-bit byte +#if !defined(CRYPTO_TYPES) +typedef uint8_t BYTE; // 8-bit byte +#define CRYPTO_TYPES +#endif typedef struct { BYTE data[16]; @@ -29,5 +33,6 @@ typedef struct { void md2_init(MD2_CTX *ctx); void md2_update(MD2_CTX *ctx, const BYTE data[], size_t len); void md2_final(MD2_CTX *ctx, BYTE hash[]); // size of hash must be MD2_BLOCK_SIZE +void md2(BYTE hash[], BYTE data[], size_t len); #endif // MD2_H diff --git a/md2_test.c b/md2_test.c index 883f20a..fb74dbe 100644 --- a/md2_test.c +++ b/md2_test.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "md2.h" /*********************** FUNCTION DEFINITIONS ***********************/ @@ -32,20 +33,20 @@ int md2_test() int pass = 1; md2_init(&ctx); - md2_update(&ctx, text1, strlen(text1)); + md2_update(&ctx, text1, strlen((const char *)text1)); md2_final(&ctx, buf); pass = pass && !memcmp(hash1, buf, MD2_BLOCK_SIZE); // Note that the MD2 object can be re-used. md2_init(&ctx); - md2_update(&ctx, text2, strlen(text2)); + md2_update(&ctx, text2, strlen((const char *)text2)); md2_final(&ctx, buf); pass = pass && !memcmp(hash2, buf, MD2_BLOCK_SIZE); // Note that the data is added in two chunks. md2_init(&ctx); - md2_update(&ctx, text3_1, strlen(text3_1)); - md2_update(&ctx, text3_2, strlen(text3_2)); + md2_update(&ctx, text3_1, strlen((const char *)text3_1)); + md2_update(&ctx, text3_2, strlen((const char *)text3_2)); md2_final(&ctx, buf); pass = pass && !memcmp(hash3, buf, MD2_BLOCK_SIZE); @@ -54,5 +55,10 @@ int md2_test() int main() { - printf("MD2 tests: %s\n", md2_test() ? "SUCCEEDED" : "FAILED"); + int ret; // 0 ==> test failed, != 0 ==> test suceeded + + ret = md2_test(); + printf("MD2 Tests: %s\n", ret ? "SUCCEEDED" : "FAILED"); + + exit(ret == 0 ? 1 : 0); } diff --git a/md5.c b/md5.c index cdba052..d5243b8 100644 --- a/md5.c +++ b/md5.c @@ -187,3 +187,12 @@ void md5_final(MD5_CTX *ctx, BYTE hash[]) hash[i + 12] = (ctx->state[3] >> (i * 8)) & 0x000000ff; } } + +void md5(BYTE hash[], BYTE data[], size_t len) +{ + MD5_CTX ctx; + + md5_init(&ctx); + md5_update(&ctx, data, len); + md5_final(&ctx,hash); +} diff --git a/md5.h b/md5.h index 1370387..37251e8 100644 --- a/md5.h +++ b/md5.h @@ -11,13 +11,17 @@ /*************************** HEADER FILES ***************************/ #include +#include /****************************** MACROS ******************************/ #define MD5_BLOCK_SIZE 16 // MD5 outputs a 16 byte digest /**************************** DATA TYPES ****************************/ -typedef unsigned char BYTE; // 8-bit byte -typedef unsigned int WORD; // 32-bit word, change to "long" for 16-bit machines +#if !defined(CRYPTO_TYPES) +typedef uint8_t BYTE; // 8-bit byte +typedef uint32_t WORD; // 32-bit word, change to "long" for 16-bit machines +#define CRYPTO_TYPES +#endif typedef struct { BYTE data[64]; @@ -30,5 +34,6 @@ typedef struct { void md5_init(MD5_CTX *ctx); void md5_update(MD5_CTX *ctx, const BYTE data[], size_t len); void md5_final(MD5_CTX *ctx, BYTE hash[]); +void md5(BYTE hash[], BYTE data[], size_t len); #endif // MD5_H diff --git a/md5_test.c b/md5_test.c index e945c8b..0f6112a 100644 --- a/md5_test.c +++ b/md5_test.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "md5.h" /*********************** FUNCTION DEFINITIONS ***********************/ @@ -32,20 +33,20 @@ int md5_test() int pass = 1; md5_init(&ctx); - md5_update(&ctx, text1, strlen(text1)); + md5_update(&ctx, text1, strlen((const char *)text1)); md5_final(&ctx, buf); pass = pass && !memcmp(hash1, buf, MD5_BLOCK_SIZE); // Note the MD5 object can be reused. md5_init(&ctx); - md5_update(&ctx, text2, strlen(text2)); + md5_update(&ctx, text2, strlen((const char *)text2)); md5_final(&ctx, buf); pass = pass && !memcmp(hash2, buf, MD5_BLOCK_SIZE); // Note the data is being added in two chunks. md5_init(&ctx); - md5_update(&ctx, text3_1, strlen(text3_1)); - md5_update(&ctx, text3_2, strlen(text3_2)); + md5_update(&ctx, text3_1, strlen((const char *)text3_1)); + md5_update(&ctx, text3_2, strlen((const char *)text3_2)); md5_final(&ctx, buf); pass = pass && !memcmp(hash3, buf, MD5_BLOCK_SIZE); @@ -54,7 +55,10 @@ int md5_test() int main() { - printf("MD5 tests: %s\n", md5_test() ? "SUCCEEDED" : "FAILED"); + int ret; // 0 ==> test failed, != 0 ==> test suceeded - return(0); + ret = md5_test(); + printf("MD5 Tests: %s\n", ret ? "SUCCEEDED" : "FAILED"); + + exit(ret == 0 ? 1 : 0); } diff --git a/rot-13.c b/rot-13.c index 0ab8497..ef2d2ec 100644 --- a/rot-13.c +++ b/rot-13.c @@ -11,25 +11,26 @@ /*************************** HEADER FILES ***************************/ #include +#include #include "rot-13.h" /*********************** FUNCTION DEFINITIONS ***********************/ -void rot13(char str[]) +void rot13(BYTE *buf, size_t len) { - int case_type, idx, len; + int idx; - for (idx = 0, len = strlen(str); idx < len; idx++) { - // Only process alphabetic characters. - if (str[idx] < 'A' || (str[idx] > 'Z' && str[idx] < 'a') || str[idx] > 'z') - continue; - // Determine if the char is upper or lower case. - if (str[idx] >= 'a') - case_type = 'a'; - else - case_type = 'A'; - // Rotate the char's value, ensuring it doesn't accidentally "fall off" the end. - str[idx] = (str[idx] + 13) % (case_type + 26); - if (str[idx] < 26) - str[idx] += case_type; - } + for (idx = 0; idx < len; idx++) { + + // Only process alphabetic characters + if (isalpha(buf[idx])) { + + // lower case rotation + if (islower(buf[idx])) { + buf[idx] = (((buf[idx] - 'a') + 13) % 26) + 'a'; + // UPPER case rotation + } else { + buf[idx] = (((buf[idx] - 'A') + 13) % 26) + 'A'; + } + } + } } diff --git a/rot-13.h b/rot-13.h index 4c581c3..8381968 100644 --- a/rot-13.h +++ b/rot-13.h @@ -11,10 +11,17 @@ /*************************** HEADER FILES ***************************/ #include +#include + +/**************************** DATA TYPES ****************************/ +#if !defined(CRYPTO_TYPES) +typedef uint8_t BYTE; // 8-bit byte +#define CRYPTO_TYPES +#endif /*********************** FUNCTION DECLARATIONS **********************/ // Performs IN PLACE rotation of the input. Assumes input is NULL terminated. // Preserves each charcter's case. Ignores non alphabetic characters. -void rot13(char str[]); +void rot13(BYTE *buf, size_t len); #endif // ROT13_H diff --git a/rot-13_test.c b/rot-13_test.c index a6fd01d..ec9f0b6 100644 --- a/rot-13_test.c +++ b/rot-13_test.c @@ -14,6 +14,7 @@ /*************************** HEADER FILES ***************************/ #include #include +#include #include "rot-13.h" /*********************** FUNCTION DEFINITIONS ***********************/ @@ -23,22 +24,28 @@ int rot13_test() char code[] = {"NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm"}; char buf[1024]; int pass = 1; + size_t len; // To encode, just apply ROT-13. - strcpy(buf, text); - rot13(buf); - pass = pass && !strcmp(code, buf); + memset(buf, 0, sizeof(buf)); + len = sizeof(text); + memcpy(buf, text, len); + rot13((BYTE *)buf, len); + pass = pass && (memcmp(code, buf, len) == 0); // To decode, just re-apply ROT-13. - rot13(buf); - pass = pass && !strcmp(text, buf); + rot13((BYTE *)buf, len); + pass = pass && (memcmp(text, buf, len) == 0); return(pass); } int main() { - printf("ROT-13 tests: %s\n", rot13_test() ? "SUCCEEDED" : "FAILED"); + int ret; // 0 ==> test failed, != 0 ==> test suceeded - return(0); + ret = rot13_test(); + printf("ROT-13 Tests: %s\n", ret ? "SUCCEEDED" : "FAILED"); + + exit(ret == 0 ? 1 : 0); } diff --git a/sha1.c b/sha1.c index 2f9622d..da32a28 100644 --- a/sha1.c +++ b/sha1.c @@ -147,3 +147,12 @@ void sha1_final(SHA1_CTX *ctx, BYTE hash[]) hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000ff; } } + +void sha1(BYTE hash[], BYTE data[], size_t len) +{ + SHA1_CTX ctx; + + sha1_init(&ctx); + sha1_update(&ctx, data, len); + sha1_final(&ctx,hash); +} diff --git a/sha1.h b/sha1.h index f32bb7c..7f1e9ef 100644 --- a/sha1.h +++ b/sha1.h @@ -11,13 +11,17 @@ /*************************** HEADER FILES ***************************/ #include +#include /****************************** MACROS ******************************/ #define SHA1_BLOCK_SIZE 20 // SHA1 outputs a 20 byte digest /**************************** DATA TYPES ****************************/ -typedef unsigned char BYTE; // 8-bit byte -typedef unsigned int WORD; // 32-bit word, change to "long" for 16-bit machines +#if !defined(CRYPTO_TYPES) +typedef uint8_t BYTE; // 8-bit byte +typedef uint32_t WORD; // 32-bit word, change to "long" for 16-bit machines +#define CRYPTO_TYPES +#endif typedef struct { BYTE data[64]; @@ -31,5 +35,6 @@ typedef struct { void sha1_init(SHA1_CTX *ctx); void sha1_update(SHA1_CTX *ctx, const BYTE data[], size_t len); void sha1_final(SHA1_CTX *ctx, BYTE hash[]); +void sha1(BYTE hash[], BYTE data[], size_t len); #endif // SHA1_H diff --git a/sha1_test.c b/sha1_test.c index 6c78f7d..716202e 100644 --- a/sha1_test.c +++ b/sha1_test.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "sha1.h" /*********************** FUNCTION DEFINITIONS ***********************/ @@ -32,18 +33,18 @@ int sha1_test() int pass = 1; sha1_init(&ctx); - sha1_update(&ctx, text1, strlen(text1)); + sha1_update(&ctx, text1, strlen((const char *)text1)); sha1_final(&ctx, buf); pass = pass && !memcmp(hash1, buf, SHA1_BLOCK_SIZE); sha1_init(&ctx); - sha1_update(&ctx, text2, strlen(text2)); + sha1_update(&ctx, text2, strlen((const char *)text2)); sha1_final(&ctx, buf); pass = pass && !memcmp(hash2, buf, SHA1_BLOCK_SIZE); sha1_init(&ctx); for (idx = 0; idx < 100000; ++idx) - sha1_update(&ctx, text3, strlen(text3)); + sha1_update(&ctx, text3, strlen((const char *)text3)); sha1_final(&ctx, buf); pass = pass && !memcmp(hash3, buf, SHA1_BLOCK_SIZE); @@ -52,7 +53,10 @@ int sha1_test() int main() { - printf("SHA1 tests: %s\n", sha1_test() ? "SUCCEEDED" : "FAILED"); + int ret; // 0 ==> test failed, != 0 ==> test suceeded - return(0); + ret = sha1_test(); + printf("SHA1 Tests: %s\n", ret ? "SUCCEEDED" : "FAILED"); + + exit(ret == 0 ? 1 : 0); } diff --git a/sha256.c b/sha256.c index eb9c5c0..6e65075 100644 --- a/sha256.c +++ b/sha256.c @@ -156,3 +156,12 @@ void sha256_final(SHA256_CTX *ctx, BYTE hash[]) hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0x000000ff; } } + +void sha256(BYTE hash[], BYTE data[], size_t len) +{ + SHA256_CTX ctx; + + sha256_init(&ctx); + sha256_update(&ctx, data, len); + sha256_final(&ctx,hash); +} diff --git a/sha256.h b/sha256.h index 7123a30..c113981 100644 --- a/sha256.h +++ b/sha256.h @@ -11,13 +11,17 @@ /*************************** HEADER FILES ***************************/ #include +#include /****************************** MACROS ******************************/ #define SHA256_BLOCK_SIZE 32 // SHA256 outputs a 32 byte digest /**************************** DATA TYPES ****************************/ -typedef unsigned char BYTE; // 8-bit byte -typedef unsigned int WORD; // 32-bit word, change to "long" for 16-bit machines +#if !defined(CRYPTO_TYPES) +typedef uint8_t BYTE; // 8-bit byte +typedef uint32_t WORD; // 32-bit word, change to "long" for 16-bit machines +#define CRYPTO_TYPES +#endif typedef struct { BYTE data[64]; @@ -30,5 +34,6 @@ typedef struct { void sha256_init(SHA256_CTX *ctx); void sha256_update(SHA256_CTX *ctx, const BYTE data[], size_t len); void sha256_final(SHA256_CTX *ctx, BYTE hash[]); +void sha256(BYTE hash[], BYTE data[], size_t len); #endif // SHA256_H diff --git a/sha256_test.c b/sha256_test.c index 726a668..5014922 100644 --- a/sha256_test.c +++ b/sha256_test.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "sha256.h" /*********************** FUNCTION DEFINITIONS ***********************/ @@ -35,18 +36,18 @@ int sha256_test() int pass = 1; sha256_init(&ctx); - sha256_update(&ctx, text1, strlen(text1)); + sha256_update(&ctx, text1, strlen((const char *)text1)); sha256_final(&ctx, buf); pass = pass && !memcmp(hash1, buf, SHA256_BLOCK_SIZE); sha256_init(&ctx); - sha256_update(&ctx, text2, strlen(text2)); + sha256_update(&ctx, text2, strlen((const char *)text2)); sha256_final(&ctx, buf); pass = pass && !memcmp(hash2, buf, SHA256_BLOCK_SIZE); sha256_init(&ctx); for (idx = 0; idx < 100000; ++idx) - sha256_update(&ctx, text3, strlen(text3)); + sha256_update(&ctx, text3, strlen((const char *)text3)); sha256_final(&ctx, buf); pass = pass && !memcmp(hash3, buf, SHA256_BLOCK_SIZE); @@ -55,7 +56,10 @@ int sha256_test() int main() { - printf("SHA-256 tests: %s\n", sha256_test() ? "SUCCEEDED" : "FAILED"); + int ret; // 0 ==> test failed, != 0 ==> test suceeded - return(0); + ret = sha256_test(); + printf("SHA-256 Tests: %s\n", ret ? "SUCCEEDED" : "FAILED"); + + exit(ret == 0 ? 1 : 0); } diff --git a/speck128128.c b/speck128128.c new file mode 100644 index 0000000..6539921 --- /dev/null +++ b/speck128128.c @@ -0,0 +1,51 @@ +/********************************************************************* +* Filename: speck128128.c +* Author: Landon Curt Noll (http://www.isthe.com/chongo/address.html) +* Copyright: This code is in the public domain. +* Disclaimer: This code is presented "as is" without any guarantees. +* NOTE: The author does NOT endorse this algorithm. +* Details: Implementation of the Speck128/128 encryption algorithm with key expansion. +* Algorithm specification can be found here: https://eprint.iacr.org/2013/404.pdf +*********************************************************************/ + +/*************************** HEADER FILES ***************************/ +#include +#include "speck128128.h" + +#define ROR(x, r) (((x) >> (r)) | ((x) << (64 - (r)))) +#define ROL(x, r) (((x) << (r)) | ((x) >> (64 - (r)))) +#define R(x, y, k) ((x) = ROR((x), 8), (x) += (y), (x) ^= (k), (y) = ROL((y), 3), (y) ^= (x)) +#define ROUNDS 32 + +/*********************** FUNCTION DEFINITIONS ***********************/ +void +speck128128(uint64_t const plain_text[static 2], uint64_t cipher_text[static 2], uint64_t const key[static 2]) +{ + uint64_t y; // plaintext word 0 + uint64_t x; // plaintext word 1 + uint64_t b; // key word 0 + uint64_t a; // key word 1 + int i; + + // load plain text + y = plain_text[0]; + x = plain_text[1]; + + // load key + b = key[0]; + a = key[1]; + + // pre-round + R(x, y, b); + + // Speck rounds + for (i=0; i < ROUNDS; ++i) { + R(a, b, i); + R(x, y, b); + } + + // return cipher text + cipher_text[0] = y; + cipher_text[1] = x; + return; +} diff --git a/speck128128.h b/speck128128.h new file mode 100644 index 0000000..8bbac40 --- /dev/null +++ b/speck128128.h @@ -0,0 +1,26 @@ +/********************************************************************* +* Filename: speck128128.h +* Author: Landon Curt Noll (http://www.isthe.com/chongo/address.html) +* Copyright: This code is in the public domain. +* Disclaimer: This code is presented "as is" without any guarantees. +* NOTE: The author does NOT endorse this algorithm. +* Details: Implementation of the Speck128/128 encryption algorithm with key expansion. +* https://eprint.iacr.org/2013/404.pdf +*********************************************************************/ + +#ifndef SPECK128128_H +#define SPECK128128_H + +/*************************** HEADER FILES ***************************/ +#include + +/****************************** MACROS ******************************/ +#define SPECK128128_BLOCK_SIZE 16 // Speck128/128 operates on 16 bytes at a time + +/**************************** DATA TYPES ****************************/ + +/*********************** FUNCTION DECLARATIONS **********************/ +// Encryplain_texts +void speck128128(uint64_t const plain_text[static 2], uint64_t cipher_text[static 2], uint64_t const key[static 2]); + +#endif // SPECK128128_H diff --git a/speck128128_test.c b/speck128128_test.c new file mode 100644 index 0000000..ff77eb2 --- /dev/null +++ b/speck128128_test.c @@ -0,0 +1,93 @@ +/********************************************************************* +* Filename: speck128128_test.c +* Author: Landon Curt Noll (http://www.isthe.com/chongo/address.html) +* Copyright: This code is in the public domain. +* Disclaimer: This code is presented "as is" without any guarantees. +* NOTE: The author does NOT endorse this algorithm. +* Details: Implementation of the Speck128/128 encryption algorithm with key expansion. +* Algorithm specification can be found here: https://eprint.iacr.org/2013/404.pdf +*********************************************************************/ + +/*************************** HEADER FILES ***************************/ +#include +#include +#include +#include +#include "speck128128.h" + +#define TEST_WORDS (32) + +/*********************** FUNCTION DEFINITIONS ***********************/ +int speck128128_test() +{ + // j-random plain text + uint64_t const plain_text[TEST_WORDS] = { + 0x0123456789abcdef, 0xfedcba9876543210, + 0x3900e49972035990, 0x86f910e0c3d54776, + 0xc2fdc49498df33e6, 0xcac5a085fc51660a, + 0x177be2883036a67a, 0x23a0fdca4012c545, + 0x46208f3a607126a3, 0x033abf878b08a2ec, + 0x3f31cc3a8c80e83d, 0x3e3073ccf36f9f7d, + 0x018c78ac65e8c984, 0x01d98df913ab7caf, + 0x7ad1cbb608e85105, 0x13dcca88d9ab8faf, + 0xc170a6c90a533183, 0x325b824c239f9bf4, + 0x65310d337798f928, 0x34532b7b8e8723ca, + 0xd66daaa2845c0fe1, 0xf8f5604a2f4732bc, + 0x90534a156ca95987, 0xcabb6639898557a1, + 0x982ca1424d8552ab, 0xbd1436bfa0b2f69a, + 0xfe8f58885aa69974, 0x49d2fdb66e1d7be4, + 0x7d4f406255f3eabb, 0xbfd15a0c7d83bfb6, + 0xc2275dad2ef776bc, 0x257b72a934d81856, + }; + // 128-bit encryption key + uint64_t const key[] = { + 0xfeedfacedeedbeef, 0x31415926cafef00d + }; + // encrypted plain text + uint64_t cipher_text[TEST_WORDS]; + // verified encrypted plain text + uint64_t const cipher_answer[TEST_WORDS] = { + 0x7043bb38d771b03c, 0x46d49489a35a8e87, + 0x0bd7b3fabb9a53fc, 0xc7988bd7133b124e, + 0xd7c852854c26feb4, 0x03e3836a508cc5df, + 0xd061ddf3a04715ec, 0xc9aa3363dcdd0f16, + 0x11af02adaefb6950, 0x0ecf90075c1ffd49, + 0x86b2038ade43f4d9, 0x78cda3c8c9d5f76d, + 0x9e0acf5e651937c2, 0xe4dda6fd1d0c0813, + 0x7338e77207d61e6b, 0xe1302dc0ecb099f3, + 0xa76736ed596fc28f, 0x2e9afec560e3dfe6, + 0x68d36b466c350f29, 0xdeb9d921dd64f8b4, + 0xf43bcb1c95d9e777, 0x7a52326b6e8a83bd, + 0xf734cabbbddcb012, 0x4a4270ef09416b56, + 0x4344c3b64966c573, 0x14b192c6b77547ee, + 0xafe21b4289d7929b, 0x15b5c93eec7b7e55, + 0xc99398b54194a317, 0x103ca3f17f7841f1, + 0xd56c55b24a4505ca, 0xbb832226c8d0aebc, + }; + int pass; // 0 ==> cipher_text was wrong, 1 ==> cipher_text is OK + int i; + + // encrypt test vector + for (i=0; i < TEST_WORDS; i += 2) { + speck128128(plain_text+i, cipher_text+i, key); + // printf("0x%016lx, 0x%016lx,\n", cipher_text[i], cipher_text[i+1]); + } + + // test answer + if (memcmp(cipher_text, cipher_answer, sizeof(cipher_answer)) == 0) { + pass = 1; + } else { + pass = 0; + } + return(pass); +} + +int main() +{ + int ret; // 0 ==> test failed, != 0 ==> test suceeded + + ret = speck128128_test(); + printf("Speck128/128 Tests: %s\n", ret ? "SUCCEEDED" : "FAILED"); + + exit(ret == 0 ? 1 : 0); +}