DES_HW.C


[View full width]

////////////////////////////////////////////////////////////////// // 3DES encryption example. // // Copyright(c) 2003-2004 Impulse Accelerated Technologies, Inc. // // This implementation is based on public domain C source code by // P. Karn and is similar to the algorithm described in Part V of // Applied Cryptography by Bruce Schneier. // #ifdef WIN32 #include <windows.h> #endif #include <stdio.h> #include "co.h" #include "co_math.h" #include "cosim_log.h" #include "des.h" #define BUFSIZE 16 /* buffer size for FIFO in hardware */ extern void des_producer(co_stream config_out_encrypt, co_stream config_out_decrypt, co_stream blocks_out, co_signal encrypt_c, co_parameter blocks_param); extern void des_consumer(co_stream ic_decrypted_blocks, co_signal decrypt_finished); extern void des_c(co_signal task_signal, co_signal next_task_signal); // Primitive function F. // Input is r, subkey array in keys, output is XORed into l. // Each round consumes eight 6-bit subkeys, one for // each of the 8 S-boxes, 2 longs for each round. // Each long contains four 6-bit subkeys, each taking up a byte. // The first long contains, from high to low end, the subkeys for // S-boxes 1, 3, 5 & 7; the second contains the subkeys for S-boxes // 2, 4, 6 & 8 (using the origin-1 S-box numbering in the standard, // not the origin-0 numbering used elsewhere in this code) // See comments elsewhere about the pre-rotated values of r and Spbox. // #define F_IC(l,r,key){\ work = ((r >> 4) | (r << 28)) ^ key[0];\ l ^= Spbox6[work & 0x3f];\ l ^= Spbox4[(work >> 8) & 0x3f];\ l ^= Spbox2[(work >> 16) & 0x3f];\ l ^= Spbox0[(work >> 24) & 0x3f];\ work = r ^ key[1];\ l ^= Spbox7[work & 0x3f];\ l ^= Spbox5[(work >> 8) & 0x3f];\ l ^= Spbox3[(work >> 16) & 0x3f];\ l ^= Spbox1[(work >> 24) & 0x3f];\ } // This is the 3DES Impulse C hardware process. The inner loops will be // automatically pipelined by the Impulse C compiler to take advantage of the // target FPGA architecture. // void des_ic(co_stream config_in, co_stream blocks_in, co_stream blocks_out, co_parameter decrypt_param) { co_error error; co_int8 i, k; co_uint8 block[8]; co_uint32 ks[DES_KS_DEPTH][2]; co_uint32 left, right, work; co_uint32 Spbox0[SPBOX_Y]; co_uint32 Spbox1[SPBOX_Y]; co_uint32 Spbox2[SPBOX_Y]; co_uint32 Spbox3[SPBOX_Y]; co_uint32 Spbox4[SPBOX_Y]; co_uint32 Spbox5[SPBOX_Y]; co_uint32 Spbox6[SPBOX_Y]; co_uint32 Spbox7[SPBOX_Y]; co_int32 decrypt = (int)decrypt_param; IF_SIM( cosim_logwindow log; ) if ( decrypt == DES_DECRYPT ) { IF_SIM ( log = cosim_logwindow_create("des_ic decrypt"); ) } else { IF_SIM ( log = cosim_logwindow_create("des_ic encrypt"); ) } // Get the key schedule, fill local array (note: this could also be // done using a shared memory scheme). // co_stream_open(config_in, O_RDONLY, UINT_TYPE(32)); IF_SIM( cosim_logwindow_fwrite(log, "3DES [Impulse C] reading keyschedule and SP boxes. ..\n"); ) for ( k = 0; k < 2; k++ ) { for ( i = 0; i < DES_KS_DEPTH; i++ ) { if ( co_stream_read(config_in, &ks[i][k], sizeof(uint32)) == co_err_none ) { } } } for ( k = 0; k < SPBOX_Y; k++ ) { co_stream_read(config_in, &Spbox0[k], sizeof(uint32)); } for ( k = 0; k < SPBOX_Y; k++ ) { co_stream_read(config_in, &Spbox1[k], sizeof(uint32)); } for ( k = 0; k < SPBOX_Y; k++ ) { co_stream_read(config_in, &Spbox2[k], sizeof(uint32)); } for ( k = 0; k < SPBOX_Y; k++ ) { co_stream_read(config_in, &Spbox3[k], sizeof(uint32)); } for ( k = 0; k < SPBOX_Y; k++ ) { co_stream_read(config_in, &Spbox4[k], sizeof(uint32)); } for ( k = 0; k < SPBOX_Y; k++ ) { co_stream_read(config_in, &Spbox5[k], sizeof(uint32)); } for ( k = 0; k < SPBOX_Y; k++ ) { co_stream_read(config_in, &Spbox6[k], sizeof(uint32)); } for ( k = 0; k < SPBOX_Y; k++ ) { co_stream_read(config_in, &Spbox7[k], sizeof(uint32)); } co_stream_close(config_in); /* Now read in the data, one block at a time */ co_stream_open(blocks_in, O_RDONLY, UINT_TYPE(8)); co_stream_open(blocks_out, O_WRONLY, UINT_TYPE(8)); IF_SIM( cosim_logwindow_fwrite(log, "3DES [Impulse C] processing blocks...\n"); ) while ( co_stream_read(blocks_in, &block[0], sizeof(uint8)) == co_err_none ) { for ( i = 1; i < DES_BLOCKSIZE; i++ ) { error = co_stream_read(blocks_in, &block[i], sizeof(uint8)); if ( error != co_err_none ) break; } if ( error != co_err_none ) break; // Process the block... // Read input block and place in left/right in big-endian order // left = ((co_uint32)block[0] << 24) | ((co_uint32)block[1] << 16) | ((co_uint32)block[2] << 8) | (co_uint32)block[3]; right = ((co_uint32)block[4] << 24) | ((co_uint32)block[5] << 16) | ((co_uint32)block[6] << 8) | (co_uint32)block[7]; // Hoey's clever initial permutation algorithm, from Outerbridge // (see Schneier p 478) // // The convention here is the same as Outerbridge: rotate each // register left by 1 bit, i.e., so that "left" contains permuted // input bits 2, 3, 4, ... 1 and "right" contains 33, 34, 35, ... 32 // (using origin-1 numbering as in the FIPS). This allows us to avoid // one of the two rotates that would otherwise be required in each of // the 16 rounds. // work = ((left >> 4) ^ right) & 0x0f0f0f0f; right ^= work; left ^= work << 4; work = ((left >> 16) ^ right) & 0xffff; right ^= work; left ^= work << 16; work = ((right >> 2) ^ left) & 0x33333333; left ^= work; right ^= (work << 2); work = ((right >> 8) ^ left) & 0xff00ff; left ^= work; right ^= (work << 8); right = (right << 1) | (right >> 31); work = (left ^ right) & 0xaaaaaaaa; left ^= work; right ^= work; left = (left << 1) | (left >> 31); /* First key */ F_IC(left,right,ks[0]); F_IC(right,left,ks[1]); F_IC(left,right,ks[2]); F_IC(right,left,ks[3]); F_IC(left,right,ks[4]); F_IC(right,left,ks[5]); F_IC(left,right,ks[6]); F_IC(right,left,ks[7]); F_IC(left,right,ks[8]); F_IC(right,left,ks[9]); F_IC(left,right,ks[10]); F_IC(right,left,ks[11]); F_IC(left,right,ks[12]); F_IC(right,left,ks[13]); F_IC(left,right,ks[14]); F_IC(right,left,ks[15]); /* Second key (must be created in opposite mode to first key) */ F_IC(right,left,ks[16]); F_IC(left,right,ks[17]); F_IC(right,left,ks[18]); F_IC(left,right,ks[19]); F_IC(right,left,ks[20]); F_IC(left,right,ks[21]); F_IC(right,left,ks[22]); F_IC(left,right,ks[23]); F_IC(right,left,ks[24]); F_IC(left,right,ks[25]); F_IC(right,left,ks[26]); F_IC(left,right,ks[27]); F_IC(right,left,ks[28]); F_IC(left,right,ks[29]); F_IC(right,left,ks[30]); F_IC(left,right,ks[31]); /* Third key */ F_IC(left,right,ks[32]); F_IC(right,left,ks[33]); F_IC(left,right,ks[34]); F_IC(right,left,ks[35]); F_IC(left,right,ks[36]); F_IC(right,left,ks[37]); F_IC(left,right,ks[38]); F_IC(right,left,ks[39]); F_IC(left,right,ks[40]); F_IC(right,left,ks[41]); F_IC(left,right,ks[42]); F_IC(right,left,ks[43]); F_IC(left,right,ks[44]); F_IC(right,left,ks[45]); F_IC(left,right,ks[46]); F_IC(right,left,ks[47]); /* Inverse permutation, also from Hoey via Outerbridge and Schneier */ right = (right << 31) | (right >> 1); work = (left ^ right) & 0xaaaaaaaa; left ^= work; right ^= work; left = (left >> 1) | (left << 31); work = ((left >> 8) ^ right) & 0xff00ff; right ^= work; left ^= work << 8; work = ((left >> 2) ^ right) & 0x33333333; right ^= work; left ^= work << 2; work = ((right >> 16) ^ left) & 0xffff; left ^= work; right ^= work << 16; work = ((right >> 4) ^ left) & 0x0f0f0f0f; left ^= work; right ^= work << 4; /* Put the block into the output stream with final swap */ block[0] = (co_int8) (right >> 24); block[1] = (co_int8) (right >> 16); block[2] = (co_int8) (right >> 8); block[3] = (co_int8) right; block[4] = (co_int8) (left >> 24); block[5] = (co_int8) (left >> 16); block[6] = (co_int8) (left >> 8); block[7] = (co_int8) left; for ( i = 0; i < DES_BLOCKSIZE; i++ ) { co_stream_write(blocks_out, &block[i], sizeof(uint8)); } } IF_SIM( cosim_logwindow_fwrite(log, "3DES [Impulse C] done processing!\n"); ) co_stream_close(blocks_out); co_stream_close(blocks_in); } /////////////////////////////////////////////////// // This is the configuration function. // void config_des(void *arg) { int blocks = (int)arg; co_stream config_encrypt_ic, config_decrypt_ic, blocks_plaintext_ic, blocks_encrypted_ic, blocks_decrypted_ic; co_signal encrypt_c, encrypt_finished_c, decrypt_finished_c; co_process producer_process; co_process des_encrypt_ic_process; co_process des_encrypt_c_process; co_process des_decrypt_ic_process; co_process des_decrypt_c_process; co_process consumer_process; IF_SIM( if ( ! cosim_logwindow_init() ) { printf("cosim_logwindow_init failed!\n"); }) encrypt_c = co_signal_create("encrypt_c"); encrypt_finished_c = co_signal_create("encrypt_finished_c"); decrypt_finished_c = co_signal_create("decrypt_finished_c"); config_encrypt_ic = co_stream_create("config_encrypt_ic", UINT_TYPE(32), BUFSIZE); config_decrypt_ic = co_stream_create("config_decrypt_ic", UINT_TYPE(32), BUFSIZE); blocks_plaintext_ic = co_stream_create("blocks_plaintext_ic", UINT_TYPE(8), BUFSIZE); blocks_encrypted_ic = co_stream_create("blocks_encrypted_ic", UINT_TYPE(8), BUFSIZE); blocks_decrypted_ic = co_stream_create("blocks_decrypted_ic", UINT_TYPE(8), BUFSIZE); producer_process = co_process_create("des_producer", (co_function)des_producer, 5, config_encrypt_ic, config_decrypt_ic, blocks_plaintext_ic, encrypt_c, blocks); des_encrypt_ic_process = co_process_create("des_encrypt_ic", (co_function)des_ic, 4, config_encrypt_ic, blocks_plaintext_ic, blocks_encrypted_ic, DES_ENCRYPT); des_encrypt_c_process = co_process_create("des_encrypt_c", (co_function)des_c, 2, encrypt_c, encrypt_finished_c); des_decrypt_ic_process = co_process_create("des_decrypt_ic", (co_function)des_ic, 4, config_decrypt_ic, blocks_encrypted_ic, blocks_decrypted_ic, DES_DECRYPT); des_decrypt_c_process = co_process_create("des_decrypt_c", (co_function)des_c, 2, encrypt_finished_c, decrypt_finished_c); consumer_process = co_process_create("des_consumer",(co_function)des_consumer, 2, blocks_decrypted_ic, decrypt_finished_c); // Assign the encryption process to hardware co_process_config(des_encrypt_ic_process, co_loc, "PE0"); } //////////////////////////////////////////////////// // This is the co_initialize function, which is // called from main(). See 3des.c // co_architecture co_initialize(int blocks) { return(co_architecture_create("des3", "Generic_VHDL", config_des, (void *)blocks)); }



    Practical FPGA Programming in C
    Practical FPGA Programming in C
    ISBN: 0131543180
    EAN: 2147483647
    Year: 2005
    Pages: 208

    Similar book on Amazon

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net