diff --git a/myserpent.c b/myserpent.c index 82d9e4f0..b01e0dd5 100644 --- a/myserpent.c +++ b/myserpent.c @@ -1,319 +1,230 @@ -/* This is an implementation of the encryption algorithm: */ -/* Serpent by Ross Anderson, Eli Biham and Lars Knudsen */ -/* which is a candidate algorithm in the Advanced Encryption Standard */ -/* programme of the US National Institute of Standards and Technology. */ -/* Copyright in this implementation is held by Dou Qinglin. but I */ -/* hereby give permission for its free direct or derivative use subject */ -/* to acknowledgment of its origin and compliance with any conditions */ -/* that the originators of the algorithm place on its exploitation. */ - -#include -#include -#include "myserpent.h" +/** +Copyright © 2015 Odzhan +Copyright © 2008 Daniel Otte +All Rights Reserved. -#define IN -#define OUT -void linear(IN unsigned long int *li_0,IN unsigned long int *li_1,IN unsigned long int *li_2,IN unsigned long int *li_3,OUT unsigned long int *lo_0,OUT unsigned long int *lo_1,OUT unsigned long int *lo_2,OUT unsigned long int *lo_3); -void IP(IN unsigned long int *ip_i0,IN unsigned long int *ip_i1,IN unsigned long int *ip_i2,IN unsigned long int *ip_i3,OUT unsigned long int *ip_o0,OUT unsigned long int *ip_o1,OUT unsigned long int *ip_o2,OUT unsigned long int *ip_o3); -void FP(IN unsigned long int *fp_i0,IN unsigned long int *fp_i1,IN unsigned long int *fp_i2,IN unsigned long int *fp_i3,OUT unsigned long int *fp_o0,OUT unsigned long int *fp_o1,OUT unsigned long int *fp_o2,OUT unsigned long int *fp_o3); +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products +derived from this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY AUTHORS "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. */ -volatile unsigned long int takbit_in0,takbit_in1,takbit_in2,takbit_in3; +#include "serpent.h" -unsigned char takebit(unsigned char bit_num){ - unsigned char bit_out; - if (bit_num< 32) bit_out = ((takbit_in0<< bit_num )&0x80000000)>>31; - else if (bit_num< 64) bit_out = ((takbit_in1<<(bit_num-32))&0x80000000)>>31; - else if (bit_num< 96) bit_out = ((takbit_in2<<(bit_num-64))&0x80000000)>>31; - else if (bit_num< 128) bit_out = ((takbit_in3<<(bit_num-96))&0x80000000)>>31; - else ; - return (bit_out & 0x00000001); + +void serpent_whiten(serpent_blk *dst, serpent_key_t *src, int idx) { + uint8_t i; + serpent_blk *p = (serpent_blk*)&src->x[idx]; + + for (i = 0; iw[i] ^= p->w[i]; + } } -//sbox involking func, each block use 1 sbox 32 times by involking this func for 4 times -unsigned long int sb(char sb_num,unsigned long int sb_in_long){ - char sb_i[8]; - char sb_o[8]; - unsigned long int sb_out_long; - char cnt; -//data div, 32bit input divide into 8 parts, each 4bit - sb_i[0] = (sb_in_long>>28) & 0x0f; // 0~3f - sb_i[1] = (sb_in_long>>24) & 0x0f; // 4~7 - sb_i[2] = (sb_in_long>>20) & 0x0f; // 8~11 - sb_i[3] = (sb_in_long>>16) & 0x0f; // 12~15 - sb_i[4] = (sb_in_long>>12) & 0x0f; // 16~19 - sb_i[5] = (sb_in_long>> 8) & 0x0f; // 20~23 - sb_i[6] = (sb_in_long>> 4) & 0x0f; // 24~27 - sb_i[7] = (sb_in_long ) & 0x0f; // 28~31 - //judge which sbox to use,and get 8 outputs of 8 independent - switch (sb_num) +void permute(serpent_blk *out, + serpent_blk *in, int type) +{ + uint8_t cy; + uint8_t n, m; + + for (n = 0; nw[n] = 0; + } + + if (type == SERPENT_IP) { - case 0: for (cnt = 0; cnt < 8; cnt++) sb_o[cnt] = sb0(sb_i[cnt] );break; - case 1: for (cnt = 0; cnt < 8; cnt++) sb_o[cnt] = sb1(sb_i[cnt] );break; - case 2: for (cnt = 0; cnt < 8; cnt++) sb_o[cnt] = sb2(sb_i[cnt] );break; - case 3: for (cnt = 0; cnt < 8; cnt++) sb_o[cnt] = sb3(sb_i[cnt] );break; - case 4: for (cnt = 0; cnt < 8; cnt++) sb_o[cnt] = sb4(sb_i[cnt] );break; - case 5: for (cnt = 0; cnt < 8; cnt++) sb_o[cnt] = sb5(sb_i[cnt] );break; - case 6: for (cnt = 0; cnt < 8; cnt++) sb_o[cnt] = sb6(sb_i[cnt] );break; - case 7: for (cnt = 0; cnt < 8; cnt++) sb_o[cnt] = sb7(sb_i[cnt] );break; - default: for (cnt = 0; cnt < 8; cnt++) sb_o[cnt] = 0x0; break; + for (n = 0; n<16; n++) { + for (m = 0; m<8; m++) { + cy = in->w[m % 4] & 1; + in->w[m % 4] >>= 1; + out->b[n] = (cy << 7) | (out->b[n] >> 1); + } + } + } + else { + for (n = 0; n<4; n++) { + for (m = 0; m<32; m++) { + cy = in->w[n] & 1; + in->w[n] >>= 1; + out->w[m % 4] = (cy << 31) | (out->w[m % 4] >> 1); + } + } } - //combine the sbox output together - sb_out_long = (sb_o[0]<<28) + (sb_o[1]<<24) + (sb_o[2]<<20) + (sb_o[3]<<16) + (sb_o[4]<<12) + (sb_o[5]<<8) + (sb_o[6]<<4) + sb_o[7]; - - return sb_out_long; } -//define the sbox0~7 un-linear logic -char sb0(char sb0_in){ - char sb0_o; - switch (sb0_in){ - case 0x0: sb0_o= 3 ;break; - case 0x1: sb0_o= 8 ;break; - case 0x2: sb0_o= 15;break; - case 0x3: sb0_o= 1 ;break; - case 0x4: sb0_o= 10;break; - case 0x5: sb0_o= 6 ;break; - case 0x6: sb0_o= 5 ;break; - case 0x7: sb0_o= 11;break; - case 0x8: sb0_o= 14;break; - case 0x9: sb0_o= 13;break; - case 0xA: sb0_o= 4 ;break; - case 0xB: sb0_o= 2 ;break; - case 0xC: sb0_o= 7 ;break; - case 0xD: sb0_o= 0 ;break; - case 0xE: sb0_o= 9 ;break; - case 0xF: sb0_o= 12;break; - default: sb0_o= 0 ;break; - } - return sb0_o; +#define HI_NIBBLE(b) (((b) >> 4) & 0x0F) +#define LO_NIBBLE(b) ((b) & 0x0F) + +uint32_t serpent_gen_w(uint32_t *b, uint32_t i) { + uint32_t ret; + ret = b[0] ^ b[3] ^ b[5] ^ b[7] ^ GOLDEN_RATIO ^ i; + return ROTL32(ret, 11); } -char sb1(char sb1_in){ - char sb1_o; - switch (sb1_in){ - case 0x0: sb1_o= 15;break; - case 0x1: sb1_o= 12;break; - case 0x2: sb1_o= 2 ;break; - case 0x3: sb1_o= 7 ;break; - case 0x4: sb1_o= 9 ;break; - case 0x5: sb1_o= 0 ;break; - case 0x6: sb1_o= 5 ;break; - case 0x7: sb1_o= 10;break; - case 0x8: sb1_o= 1 ;break; - case 0x9: sb1_o= 11;break; - case 0xA: sb1_o= 14;break; - case 0xB: sb1_o= 8 ;break; - case 0xC: sb1_o= 6 ;break; - case 0xD: sb1_o= 13;break; - case 0xE: sb1_o= 3 ;break; - case 0xF: sb1_o= 4 ;break; - default: sb1_o= 0 ;break; +void serpent_subbytes(serpent_blk *blk, uint32_t box_idx, int type) +{ + serpent_blk tmp_blk, sb; + uint8_t *sbp; + uint8_t i, t; + + uint8_t sbox[8][8] = + { { 0x83, 0x1F, 0x6A, 0xB5, 0xDE, 0x24, 0x07, 0xC9 }, + { 0xCF, 0x72, 0x09, 0xA5, 0xB1, 0x8E, 0xD6, 0x43 }, + { 0x68, 0x97, 0xC3, 0xFA, 0x1D, 0x4E, 0xB0, 0x25 }, + { 0xF0, 0x8B, 0x9C, 0x36, 0x1D, 0x42, 0x7A, 0xE5 }, + { 0xF1, 0x38, 0x0C, 0x6B, 0x52, 0xA4, 0xE9, 0xD7 }, + { 0x5F, 0xB2, 0xA4, 0xC9, 0x30, 0x8E, 0x6D, 0x17 }, + { 0x27, 0x5C, 0x48, 0xB6, 0x9E, 0xF1, 0x3D, 0x0A }, + { 0xD1, 0x0F, 0x8E, 0xB2, 0x47, 0xAC, 0x39, 0x65 } + }; + + uint8_t sbox_inv[8][8] = + { { 0x3D, 0x0B, 0x6A, 0xC5, 0xE1, 0x74, 0x9F, 0x28 }, + { 0x85, 0xE2, 0x6F, 0x3C, 0x4B, 0x97, 0xD1, 0x0A }, + { 0x9C, 0x4F, 0xEB, 0x21, 0x30, 0xD6, 0x85, 0x7A }, + { 0x90, 0x7A, 0xEB, 0xD6, 0x53, 0x2C, 0x84, 0x1F }, + { 0x05, 0x38, 0x9A, 0xE7, 0xC2, 0x6B, 0xF4, 0x1D }, + { 0xF8, 0x92, 0x14, 0xED, 0x6B, 0x35, 0xC7, 0x0A }, + { 0xAF, 0xD1, 0x35, 0x06, 0x94, 0x7E, 0xC2, 0xB8 }, + { 0x03, 0xD6, 0xE9, 0x8F, 0xC5, 0x7B, 0x1A, 0x24 } + }; + + box_idx &= 7; + + if (type == SERPENT_ENCRYPT) { + sbp = (uint8_t*)&sbox[box_idx][0]; } - return sb1_o; + else { + sbp = (uint8_t*)&sbox_inv[box_idx][0]; + } + + for (i = 0; i<16; i += 2) { + t = sbp[i / 2]; + sb.b[i + 0] = LO_NIBBLE(t); + sb.b[i + 1] = HI_NIBBLE(t); + } + + permute(&tmp_blk, blk, SERPENT_IP); + + for (i = 0; iw[0]; + x1 = x->w[1]; + x2 = x->w[2]; + x3 = x->w[3]; + + if (enc == SERPENT_DECRYPT) { + x2 = ROTL32(x2, 10); + x0 = ROTR32(x0, 5); + x2 ^= x3 ^ (x1 << 7); + x0 ^= x1 ^ x3; + x3 = ROTR32(x3, 7); + x1 = ROTR32(x1, 1); + x3 ^= x2 ^ (x0 << 3); + x1 ^= x0 ^ x2; + x2 = ROTR32(x2, 3); + x0 = ROTR32(x0, 13); + } + else { + x0 = ROTL32(x0, 13); + x2 = ROTL32(x2, 3); + x1 ^= x0 ^ x2; + x3 ^= x2 ^ (x0 << 3); + x1 = ROTL32(x1, 1); + x3 = ROTL32(x3, 7); + x0 ^= x1 ^ x3; + x2 ^= x3 ^ (x1 << 7); + x0 = ROTL32(x0, 5); + x2 = ROTR32(x2, 10); + } + x->w[0] = x0; + x->w[1] = x1; + x->w[2] = x2; + x->w[3] = x3; } -//initial permutation -void FP(IN unsigned long int *fp_i0,IN unsigned long int *fp_i1,IN unsigned long int *fp_i2,IN unsigned long int *fp_i3,OUT unsigned long int *fp_o0,OUT unsigned long int *fp_o1,OUT unsigned long int *fp_o2,OUT unsigned long int *fp_o3){ - unsigned long int tmp_0,tmp_1,tmp_2,tmp_3; - takbit_in0 = *fp_i0; - takbit_in1 = *fp_i1; - takbit_in2 = *fp_i2; - takbit_in3 = *fp_i3; - //execute takbit function - tmp_3 = (takebit(96)<<31) + (takebit(100 )<<30) + (takebit(104 )<<29) + (takebit(108 )<<28) + (takebit(112 )<<27) + (takebit(116 )<<26) + (takebit(120 )<<25) + (takebit(124 )<<24) + (takebit(64)<<23) + (takebit(68 )<<22) + (takebit(72 )<<21) + (takebit(76 )<<20) + (takebit(80 )<<19) + (takebit(84 )<<18) + (takebit(88 )<<17) + (takebit(92 )<<16) + (takebit(32)<<15) + (takebit(36 )<<14) + (takebit(40 )<<13) + (takebit(44 )<<12) + (takebit(48 )<<11) + (takebit(52 )<<10) + (takebit(56 )<<9) + (takebit(60 )<<8) + (takebit(0 )<<7) + (takebit( 4 )<<6) + (takebit( 8 )<<5) + (takebit(12 )<<4) + (takebit(16 )<<3) + (takebit(20 )<<2) + (takebit(24 )<<1) + takebit(28 ); - tmp_2 = (takebit(97)<<31) + (takebit(101 )<<30) + (takebit(105 )<<29) + (takebit(109 )<<28) + (takebit(113 )<<27) + (takebit(117 )<<26) + (takebit(121 )<<25) + (takebit(125 )<<24) + (takebit(65)<<23) + (takebit(69 )<<22) + (takebit(73 )<<21) + (takebit(77 )<<20) + (takebit(81 )<<19) + (takebit(85 )<<18) + (takebit(89 )<<17) + (takebit(93 )<<16) + (takebit(33)<<15) + (takebit(37 )<<14) + (takebit(41 )<<13) + (takebit(45 )<<12) + (takebit(49 )<<11) + (takebit(53 )<<10) + (takebit(57 )<<9) + (takebit(61 )<<8) + (takebit(1 )<<7) + (takebit( 5 )<<6) + (takebit( 9 )<<5) + (takebit(13 )<<4) + (takebit(17 )<<3) + (takebit(21 )<<2) + (takebit(25 )<<1) + takebit(29 ); - tmp_1 = (takebit(98)<<31) + (takebit(102 )<<30) + (takebit(106 )<<29) + (takebit(110 )<<28) + (takebit(114 )<<27) + (takebit(118 )<<26) + (takebit(122 )<<25) + (takebit(126 )<<24) + (takebit(66)<<23) + (takebit(70 )<<22) + (takebit(74 )<<21) + (takebit(78 )<<20) + (takebit(82 )<<19) + (takebit(86 )<<18) + (takebit(90 )<<17) + (takebit(94 )<<16) + (takebit(34)<<15) + (takebit(38 )<<14) + (takebit(42 )<<13) + (takebit(46 )<<12) + (takebit(50 )<<11) + (takebit(54 )<<10) + (takebit(58 )<<9) + (takebit(62 )<<8) + (takebit(2 )<<7) + (takebit( 6 )<<6) + (takebit(10 )<<5) + (takebit(14 )<<4) + (takebit(18 )<<3) + (takebit(22 )<<2) + (takebit(26 )<<1) + takebit(30 ); - tmp_0 = (takebit(99)<<31) + (takebit(103 )<<30) + (takebit(107 )<<29) + (takebit(111 )<<28) + (takebit(115 )<<27) + (takebit(119 )<<26) + (takebit(123 )<<25) + (takebit(127 )<<24) + (takebit(67)<<23) + (takebit(71 )<<22) + (takebit(75 )<<21) + (takebit(79 )<<20) + (takebit(83 )<<19) + (takebit(87 )<<18) + (takebit(91 )<<17) + (takebit(95 )<<16) + (takebit(35)<<15) + (takebit(39 )<<14) + (takebit(43 )<<13) + (takebit(47 )<<12) + (takebit(51 )<<11) + (takebit(55 )<<10) + (takebit(59 )<<9) + (takebit(63 )<<8) + (takebit(3 )<<7) + (takebit( 7 )<<6) + (takebit(11 )<<5) + (takebit(15 )<<4) + (takebit(19 )<<3) + (takebit(23 )<<2) + (takebit(27 )<<1) + takebit(31 ); - //data out - *fp_o0 = tmp_0; - *fp_o1 = tmp_1; - *fp_o2 = tmp_2; - *fp_o3 = tmp_3; +void serpent_set_encrypt_key(serpent_key_t *key, void *user_key) +{ + union { + uint8_t b[32]; + uint32_t w[8]; + } s_ws; + + uint32_t i, j; + + // copy key input to local buffer + memcpy(&s_ws.b[0], user_key, SERPENT_KEY256); + + // expand the key + for (i = 0; i <= SERPENT_ROUNDS; i++) { + for (j = 0; j<4; j++) { + key->x[i][j] = serpent_gen_w(s_ws.w, i * 4 + j); + memmove(&s_ws.b, &s_ws.b[4], 7 * 4); + s_ws.w[7] = key->x[i][j]; + } + serpent_subbytes((serpent_blk*)&key->x[i], 3 - i, SERPENT_ENCRYPT); + } } -void linear(IN unsigned long int *li_0,IN unsigned long int *li_1,IN unsigned long int *li_2,IN unsigned long int *li_3,OUT unsigned long int *lo_0,OUT unsigned long int *lo_1,OUT unsigned long int *lo_2,OUT unsigned long int *lo_3){ - unsigned long int tmp_0,tmp_1,tmp_2,tmp_3; - tmp_0 = *li_0; - tmp_1 = *li_1; - tmp_2 = *li_2; - tmp_3 = *li_3; - - tmp_0 = rotl(tmp_0, 13); - tmp_2 = rotl(tmp_2, 3); - tmp_1 = tmp_1 ^ tmp_0 ^ tmp_2; - tmp_3 = tmp_3 ^ tmp_2 ^ (tmp_0 << 3); - tmp_1 = rotl(tmp_1, 1); - tmp_3 = rotl(tmp_3, 7); - tmp_0 = tmp_0 ^ tmp_1 ^ tmp_3; - tmp_2 = tmp_2 ^ tmp_3 ^ (tmp_1 << 7); - tmp_0 = rotl(tmp_0, 5); - tmp_2 = rotl(tmp_2, 22); - - *lo_0 = tmp_0; - *lo_1 = tmp_1; - *lo_2 = tmp_2; - *lo_3 = tmp_3; +void serpent_encrypt(void *in, serpent_key_t *key) +{ + int8_t i; + serpent_blk *out = in; + + i = 0; + for (;;) { + // xor with subkey + serpent_whiten(out, key, i); + // apply sbox + serpent_subbytes(out, i, SERPENT_ENCRYPT); + if (++i == SERPENT_ROUNDS) break; + // linear transformation + serpent_lt(out, SERPENT_ENCRYPT); + } + serpent_whiten(out, key, i); +} + +void serpent_decrypt(void *in, serpent_key_t *key) +{ + int8_t i; + serpent_blk *out = in; + + i = SERPENT_ROUNDS; + serpent_whiten(out, key, i); + for (;;) { + --i; + // apply sbox + serpent_subbytes(out, i, SERPENT_DECRYPT); + // xor with subkey + serpent_whiten(out, key, i); + if (i == 0) break; + // linear transformation + serpent_lt(out, SERPENT_DECRYPT); + } }