#include #include #include #include #include #include #include #include #include "cleanbench.h" #include "randnum.h" /******************** ** IDEA Encryption ** ********************* ** IDEA - International Data Encryption Algorithm. ** Based on code presented in Applied Cryptography by Bruce Schneier. ** Which was based on code developed by Xuejia Lai and James L. Massey. ** Other modifications made by Colin Plumb. ** */ /* Following constant defines the max number of loops the ** system will attempt. Keeps things from going off into the ** weeds. */ /*#define LOOP_MAX 50000L*/ #define LOOP_MAX 500000L /* ** Following constant sets the size of the arrays. ** NOTE: For the IDEA algorithm to work properly, this ** number MUST be some multiple of 8. */ #define ARRAY_SIZE 4000 #define IDEAKEYSIZE 16 #define IDEABLOCKSIZE 8 #define ROUNDS 8 #define KEYLEN (6*ROUNDS+4) #define low16(x) ((x) & 0x0FFFF) #define MUL(x,y) (x=mul(low16(x),y)) typedef uint16_t IDEAkey[KEYLEN]; static clock_t DoIDEAIteration(unsigned char *plain1, unsigned char *crypt1, unsigned char *plain2, unsigned long nloops, IDEAkey Z, IDEAkey DK); static uint16_t mul(register uint16_t a, register uint16_t b); static uint16_t inv(uint16_t x); static void en_key_idea(uint16_t userkey[8], IDEAkey Z); static void de_key_idea(IDEAkey Z, IDEAkey DK); static void cipher_idea(uint16_t in[4], uint16_t out[4], IDEAkey Z); /*********** ** DoIDEA ** ************ ** Perform IDEA encryption. Note that we time encryption & decryption ** time as being a single loop. */ double DoIDEA(void) { unsigned char* plain1 = NULL; /* First plaintext buffer */ unsigned char* crypt1 = NULL; /* Encryption buffer */ unsigned char* plain2 = NULL; /* Second plaintext buffer */ clock_t total_time = 0; int iterations = 0; IDEAkey Z, DK; uint16_t userkey[8]; int i; static bool is_adjusted = false; static int loops = 100; randnum(3); /* ** Build an encryption/decryption key */ for ( i = 0; i < 8; i++) { userkey[i] = (uint16_t)(abs_randwc((int32_t)60000) & 0xFFFF); } for(i = 0; i < KEYLEN ; i++) { Z[i] = 0; } /* ** Compute encryption/decryption subkeys */ en_key_idea(userkey,Z); de_key_idea(Z,DK); /* ** Allocate memory for buffers. We'll make 3, called plain1, ** crypt1, and plain2. It works like this: ** plain1 >>encrypt>> crypt1 >>decrypt>> plain2. ** So, plain1 and plain2 should match. ** Also, fill up plain1 with sample text. */ plain1 = malloc(ARRAY_SIZE); crypt1 = malloc(ARRAY_SIZE); plain2 = malloc(ARRAY_SIZE); /* ** Note that we build the "plaintext" by simply loading ** the array up with random numbers. */ for (i = 0;i < ARRAY_SIZE; i++) { plain1[i] = (unsigned char)(abs_randwc(255) & 0xFF); } /* ** See if we need to perform self adjustment loop. */ if (is_adjusted == false) { is_adjusted = true; /* ** Do self-adjustment. This involves initializing the ** # of loops and increasing the loop count until we ** get a number of loops that we can use. */ do { loops += 10; } while((DoIDEAIteration(plain1, crypt1, plain2, loops, Z, DK) <= MINIMUM_TICKS) && (loops < LOOP_MAX)); } /* ** All's well if we get here. Do the test. */ do { total_time += DoIDEAIteration(plain1, crypt1, plain2, loops, Z, DK); iterations += loops; } while (total_time < MINIMUM_SECONDS * CLOCKS_PER_SEC); free(plain1); free(crypt1); free(plain2); return (double)(iterations * CLOCKS_PER_SEC) / (double)total_time; } /******************** ** DoIDEAIteration ** ********************* ** Execute a single iteration of the IDEA encryption algorithm. ** Actually, a single iteration is one encryption and one ** decryption. */ static clock_t DoIDEAIteration(unsigned char *plain1, unsigned char *crypt1, unsigned char *plain2, unsigned long nloops, IDEAkey Z, IDEAkey DK) { clock_t start, stop; register unsigned long i; register unsigned long j; start = clock(); for (i = 0; i < nloops; i++) { for (j = 0; j < ARRAY_SIZE; j += sizeof(uint16_t) * 4) { cipher_idea((uint16_t *)(plain1 + j), (uint16_t *)(crypt1 + j), Z); /* Encrypt */ } for (j = 0; j < ARRAY_SIZE; j += sizeof(uint16_t) * 4) { cipher_idea((uint16_t *)(crypt1 + j), (uint16_t *)(plain2 + j), DK); /* Decrypt */ } } stop = clock(); return stop - start; } /******** ** mul ** ********* ** Performs multiplication, modulo (2**16)+1. This code is structured ** on the assumption that untaken branches are cheaper than taken ** branches, and that the compiler doesn't schedule branches. */ static uint16_t mul(register uint16_t a, register uint16_t b) { register uint32_t p; if(a) { if(b) { p=(uint32_t)(a*b); b=low16(p); a=(uint16_t)(p>>16); return(b-a+(b> 7); Z+=i&8; i&=7; } return; } /**************** ** de_key_idea ** ***************** ** Compute IDEA decryption subkeys DK from encryption ** subkeys Z. */ static void de_key_idea(IDEAkey Z, IDEAkey DK) { IDEAkey TT; int j; uint16_t t1, t2, t3; uint16_t *p; p=(uint16_t *)(TT+KEYLEN); t1=inv(*Z++); t2=-*Z++; t3=-*Z++; *--p=inv(*Z++); *--p=t3; *--p=t2; *--p=t1; for(j=1;j