From 083d7d2a1375304e61c08048426a80e2cc41c55d Mon Sep 17 00:00:00 2001 From: bg Date: Mon, 7 Aug 2006 16:33:57 +0000 Subject: [PATCH] +RC6 --- Makefile | 5 +- main-rc6-test.c | 177 ++++++++++++++++++++++++++++++++++++++++++++++++ rc6.c | 131 +++++++++++++++++++++++++++++++++++ rc6.h | 28 ++++++++ 4 files changed, 339 insertions(+), 2 deletions(-) create mode 100644 main-rc6-test.c create mode 100644 rc6.c create mode 100644 rc6.h diff --git a/Makefile b/Makefile index 4e67726..d902738 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,7 @@ -PRG = md5 +PRG = rc6 # cryptotest -OBJ = main-md5-test.o debug.o uart.o serial-tools.o md5.o +OBJ = main-rc6-test.o debug.o uart.o serial-tools.o rc6.o +# main-md5-test.o debug.o uart.o serial-tools.o md5.o # main-cast5-test.o debug.o uart.o serial-tools.o cast5.o # main.o debug.o uart.o serial-tools.o sha256-asm.o xtea-asm.o arcfour-asm.o prng.o cast5.o MCU_TARGET = atmega32 diff --git a/main-rc6-test.c b/main-rc6-test.c new file mode 100644 index 0000000..0c886d1 --- /dev/null +++ b/main-rc6-test.c @@ -0,0 +1,177 @@ +/* + * rc6 test-suit + * +*/ + +#include "config.h" +#include "serial-tools.h" +#include "uart.h" +#include "debug.h" + +#include "rc6.h" + +#include +#include +#include + + +#ifndef BOOL +#define BOOL + #ifndef __BOOL + #define __BOOL + #ifndef __BOOL__ + #define __BOOL__ + typedef enum{false=0,true=1} bool; + #endif + #endif +#endif + + + +/***************************************************************************** + * additional validation-functions * + *****************************************************************************/ + +/***************************************************************************** + * self tests * + *****************************************************************************/ + +void test_encrypt(uint8_t *block, uint8_t *key, uint16_t keylength, bool print){ + rc6_ctx_t s; + if (print){ + uart_putstr("\r\nRC6 (enc):\r\n key:\t"); + uart_hexdump(key, keylength/8); + uart_putstr("\r\n plaintext:\t"); + uart_hexdump(block, 16); + } + if (rc6_init(&s, key, keylength)){ + uart_putstr("RC6 init failed!"); + return; + } + rc6_enc(&s, block); + if (print){ + uart_putstr("\r\n ciphertext:\t"); + uart_hexdump(block, 16); + } + rc6_free(&s); +} + +void test_decrypt(uint8_t *block, uint8_t *key, uint16_t keylength, bool print){ + rc6_ctx_t s; + if (print){ + uart_putstr("\r\nRC6 (dec):\r\n key:\t"); + uart_hexdump(key, keylength/8); + uart_putstr("\r\n ciphertext:\t"); + uart_hexdump(block, 16); + } + if (rc6_init(&s, key, keylength)){ + uart_putstr("RC6 init failed!"); + return; + } + rc6_dec(&s, block); + if (print){ + uart_putstr("\r\n plaintext:\t"); + uart_hexdump(block, 16); + } + rc6_free(&s); +} + +/* + * Test vectors for encryption with RC6 + plaintext 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + user key 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + ciphertext 8f c3 a5 36 56 b1 f7 78 c1 29 df 4e 98 48 a4 1e + + plaintext 02 13 24 35 46 57 68 79 8a 9b ac bd ce df e0 f1 + user key 01 23 45 67 89 ab cd ef 01 12 23 34 45 56 67 78 + ciphertext 52 4e 19 2f 47 15 c6 23 1f 51 f6 36 7e a4 3f 18 + + plaintext 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + user key 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + ciphertext 6c d6 1b cb 19 0b 30 38 4e 8a 3f 16 86 90 ae 82 + + plaintext 02 13 24 35 46 57 68 79 8a 9b ac bd ce df e0 f1 + user key 01 23 45 67 89 ab cd ef 01 12 23 34 45 56 67 78 + 89 9a ab bc cd de ef f0 + ciphertext 68 83 29 d0 19 e5 05 04 1e 52 e9 2a f9 52 91 d4 + + plaintext 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + user key 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + ciphertext 8f 5f bd 05 10 d1 5f a8 93 fa 3f da 6e 85 7e c2 + + plaintext 02 13 24 35 46 57 68 79 8a 9b ac bd ce df e0 f1 + user key 01 23 45 67 89 ab cd ef 01 12 23 34 45 56 67 78 + 89 9a ab bc cd de ef f0 10 32 54 76 98 ba dc fe + ciphertext c8 24 18 16 f0 d7 e4 89 20 ad 16 a1 67 4e 5d 48 + * + */ + + uint8_t PROGMEM testkey[6][256/8]={ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, + 0x89, 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef, 0xf0}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, + 0x89, 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef, 0xf0, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe}}; + uint8_t PROGMEM testplain[2][128/8]={ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0x13, 0x24, 0x35, 0x46, 0x57, 0x68, 0x79, 0x8a, 0x9b, 0xac, 0xbd, 0xce, 0xdf, 0xe0, 0xf1}}; + uint8_t PROGMEM testcipher[6][128/8]={ + {0x8f, 0xc3, 0xa5, 0x36, 0x56, 0xb1, 0xf7, 0x78, 0xc1, 0x29, 0xdf, 0x4e, 0x98, 0x48, 0xa4, 0x1e}, + {0x52, 0x4e, 0x19, 0x2f, 0x47, 0x15, 0xc6, 0x23, 0x1f, 0x51, 0xf6, 0x36, 0x7e, 0xa4, 0x3f, 0x18}, + {0x6c, 0xd6, 0x1b, 0xcb, 0x19, 0x0b, 0x30, 0x38, 0x4e, 0x8a, 0x3f, 0x16, 0x86, 0x90, 0xae, 0x82}, + {0x68, 0x83, 0x29, 0xd0, 0x19, 0xe5, 0x05, 0x04, 0x1e, 0x52, 0xe9, 0x2a, 0xf9, 0x52, 0x91, 0xd4}, + {0x8f, 0x5f, 0xbd, 0x05, 0x10, 0xd1, 0x5f, 0xa8, 0x93, 0xfa, 0x3f, 0xda, 0x6e, 0x85, 0x7e, 0xc2}, + {0xc8, 0x24, 0x18, 0x16, 0xf0, 0xd7, 0xe4, 0x89, 0x20, 0xad, 0x16, 0xa1, 0x67, 0x4e, 0x5d, 0x48}}; + + +void testrun_rc6(void){ + uint16_t keysize[]={128, 128, 192, 192, 256, 256}; + uint8_t i; + uint8_t block[16]; + uint8_t key[32]; + memset(block, 0, 16); + memset(key, 0, 16); + + test_encrypt(block, key, 128, true); + for(i=0; i<6; ++i){ + memcpy_P(block, testplain[i&1], 128/8); + memcpy_P(key, testkey[i], keysize[i]/8); + test_encrypt(block, key, keysize[i], true); + memcpy_P(key, testkey[i], keysize[i]/8); + test_decrypt(block, key, keysize[i], true); + } +} + + + +/***************************************************************************** + * main * + *****************************************************************************/ + +int main (void){ + char str[20]; + + + DEBUG_INIT(); + uart_putstr("\r\n"); + + uart_putstr("\r\n\r\nCrypto-VS (RC6)\r\nloaded and running\r\n"); +restart: + while(1){ + if (!getnextwordn(str,20)) {DEBUG_S("DBG: W1\r\n"); goto error;} + if (strcmp(str, "test")) {DEBUG_S("DBG: 1b\r\n"); goto error;} + testrun_rc6(); + goto restart; + continue; + error: + uart_putstr("ERROR\r\n"); + } /* while (1) */ +} + diff --git a/rc6.c b/rc6.c new file mode 100644 index 0000000..29889a2 --- /dev/null +++ b/rc6.c @@ -0,0 +1,131 @@ +/* + * File: rc6.c + * Author: Daniel Otte + * Date: 06.08.2006 + * License: GPL + * Description: Implementation of the RC6 cipher algorithm. + * This implementation is restricted to 32-bit words and to keys up to 65535 bit in length (but this is + * quite easy to expand), but free in the choice of number of rounds (0 to 125). + * so it is RC6-32/r/b + * THIS ONLY WORKS FOR LITTEL ENDIAN!!! + */ + + #include + #include + #include "rc6.h" + #include "config.h" + + #define P32 0xB7E15163 /* e -2 */ + #define Q32 0x9E3779B9 /* Golden Ratio -1 */ + +uint32_t rotl32(uint32_t a, uint8_t n){ + n &= 0x1f; /* higher rotates would not bring anything */ + return ( (a<>(32-n)) ); + } + +uint32_t rotr32(uint32_t a, uint8_t n){ + n &= 0x1f; /* higher rotates would not bring anything */ + return ( (a>>n)| (a<<(32-n)) ); + } + + uint8_t rc6_init(rc6_ctx_t *s,void* key, uint16_t keylength){ + return rc6_initl(s, key, keylength, 20); + } + + + uint8_t rc6_initl(rc6_ctx_t *s,void* key, uint16_t keylength, uint8_t rounds){ + uint8_t i,j; + uint16_t v,p,c; + uint32_t a,b, l=0; + if (rounds>125) + return 2; + if(!(s->S=malloc((2*rounds+4)*sizeof(uint32_t)))) + return 1; + + s->rounds=rounds; + + c = keylength/32; + if (keylength%32){ + ++c; + j=(keylength%32)/8; + if(keylength%8) + ++j; + for (i=0; iS[0] = P32; + for(i=1; i<2*rounds+4; ++i){ + s->S[i] = s->S[i-1] + Q32; + } + + a=b=j=i=0; + v = 3 * ((c > 2*rounds+4)?c:(2*rounds+4)); + for(p=1; p<=v; ++p){ + a = s->S[i] = rotl32(s->S[i] + a + b, 3); + if (j==c-1){ + b = l = rotl32(l+a+b, a+b); + } else { + b = ((uint32_t*)key)[j] = rotl32(((uint32_t*)key)[j]+a+b, a+b); + } + i = (i+1) % (2*rounds+4); + j = (j+1) % c; + } + return 0; + } + + void rc6_free(rc6_ctx_t *s){ + free(s->S); + } + + #define LG_W 5 + #define A (((uint32_t*)block)[0]) + #define B (((uint32_t*)block)[1]) + #define C (((uint32_t*)block)[2]) + #define D (((uint32_t*)block)[3]) + + void rc6_enc(rc6_ctx_t *s, void* block){ + uint8_t i; + uint32_t t,u,x; /* greetings to Linux? */ + B += s->S[0]; + D += s->S[1]; + for (i=1; i<=s->rounds; ++i){ + t = rotl32(B * (2*B+1), LG_W); + u = rotl32(D * (2*D+1), LG_W); + A = rotl32((A ^ t), u) + s->S[2*i]; + C = rotl32((C ^ u), t) + s->S[2*i+1]; + x = A; + A = B; + B = C; + C = D; + D = x; + } + A += s->S[2*s->rounds+2]; + C += s->S[2*s->rounds+3]; + } + + void rc6_dec(rc6_ctx_t *s, void* block) + { + uint8_t i; + uint32_t t,u,x; /* greetings to Linux? */ + + C -= s->S[2*s->rounds+3]; + A -= s->S[2*s->rounds+2]; + + for (i=s->rounds; i>0; --i){ + x=D; + D=C; + C=B; + B=A; + A=x; + u = rotl32(D * (2*D+1), LG_W); + t = rotl32(B * (2*B+1), LG_W); + C = rotr32(C - s->S[2*i+1], t) ^ u; + A = rotr32(A - s->S[2*i+0], u) ^ t; + } + D -= s->S[1]; + B -= s->S[0]; + } + diff --git a/rc6.h b/rc6.h new file mode 100644 index 0000000..35887bc --- /dev/null +++ b/rc6.h @@ -0,0 +1,28 @@ +/* + * File: rc6.h + * Author: Daniel Otte + * Date: 06.08.2006 + * License: GPL + * Description: Implementation of the RC6 cipher algorithm. + * This implementation is restricted to 32-bit words, but free in the choice of number of rounds (0 to 255). + * so it is RC6-32/r/b + */ + + #include + + typedef struct rc6_ctx_st{ + uint8_t rounds; /* specifys the number of rounds; default: 20 */ + uint32_t* S; /* the round-keys */ + } rc6_ctx_t; + + + uint8_t rc6_init(rc6_ctx_t *s,void* key, uint16_t keylength); + + uint8_t rc6_initl(rc6_ctx_t *s,void* key, uint16_t keylength, uint8_t rounds); + + void rc6_enc(rc6_ctx_t *s, void* block); + + void rc6_dec(rc6_ctx_t *s, void* block); + + void rc6_free(rc6_ctx_t *s); +