noekeon.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. /* noekeon.c */
  2. /*
  3. This file is part of the ARM-Crypto-Lib.
  4. Copyright (C) 2006-2010 Daniel Otte (daniel.otte@rub.de)
  5. This program is free software: you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation, either version 3 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. /*
  17. * author: Daniel Otte
  18. * email: daniel.otte@rub.de
  19. * license: GPLv3 or later
  20. *
  21. *
  22. *
  23. */
  24. #include <stdint.h>
  25. #include <string.h>
  26. #ifdef __AVR__
  27. #include <avr/pgmspace.h>
  28. #endif
  29. #include <crypto/noekeon.h>
  30. // #include <crypto/cli.h>
  31. #define ROUND_NR 16
  32. #define RC_POS 0
  33. static
  34. void gamma_x(uint32_t* a){
  35. uint32_t tmp;
  36. a[1] ^= ~((a[3]) | (a[2]));
  37. a[0] ^= a[2] & a[1];
  38. tmp=a[3]; a[3]=a[0]; a[0]=tmp;
  39. a[2] ^= a[0] ^ a[1] ^ a[3];
  40. a[1] ^= ~((a[3]) | (a[2]));
  41. a[0] ^= a[2] & a[1];
  42. }
  43. #define ROTL32(a,n) (((a)<<n)|((a)>>(32-n)))
  44. #define ROTR32(a,n) (((a)>>n)|((a)<<(32-n)))
  45. static
  46. void pi1(uint32_t* a){
  47. a[1] = ROTL32(a[1], 1);
  48. a[2] = ROTL32(a[2], 5);
  49. a[3] = ROTL32(a[3], 2);
  50. }
  51. static
  52. void pi2(uint32_t* a){
  53. a[1] = ROTR32(a[1], 1);
  54. a[2] = ROTR32(a[2], 5);
  55. a[3] = ROTR32(a[3], 2);
  56. }
  57. static
  58. void theta(const uint32_t* k, uint32_t* a){
  59. uint32_t temp;
  60. temp = a[0] ^ a[2]; temp ^= ROTR32(temp, 8) ^ ROTL32(temp, 8);
  61. a[1] ^= temp;
  62. a[3] ^= temp;
  63. a[0] ^= k[0];
  64. a[1] ^= k[1];
  65. a[2] ^= k[2];
  66. a[3] ^= k[3];
  67. temp = a[1] ^ a[3]; temp ^= ROTR32(temp, 8) ^ ROTL32(temp, 8);
  68. a[0] ^= temp;
  69. a[2] ^= temp;
  70. }
  71. static
  72. void noekeon_round(uint32_t* key, uint32_t* state, uint8_t const1, uint8_t const2){
  73. ((uint8_t*)state)[RC_POS] ^= const1;
  74. theta(key, state);
  75. ((uint8_t*)state)[RC_POS] ^= const2;
  76. pi1(state);
  77. gamma_x(state);
  78. pi2(state);
  79. }
  80. uint8_t rc_tab[]
  81. #ifdef __AVR__
  82. PROGMEM
  83. #endif
  84. = {
  85. /* 0x80, */
  86. 0x1B, 0x36, 0x6C, 0xD8, 0xAB, 0x4D, 0x9A,
  87. 0x2F, 0x5E, 0xBC, 0x63, 0xC6, 0x97, 0x35, 0x6A,
  88. 0xD4
  89. };
  90. /* for more rounds
  91. 0xD4, 0xB3, 0x7D, 0xFA, 0xEF, 0xC5, 0x91, 0x39,
  92. 0x72, 0xE4, 0xD3, 0xBD, 0x61, 0xC2, 0x9F, 0x25,
  93. */
  94. static
  95. void changendian32(void* a){
  96. ((uint8_t*)a)[0] ^= ((uint8_t*)a)[3];
  97. ((uint8_t*)a)[3] ^= ((uint8_t*)a)[0];
  98. ((uint8_t*)a)[0] ^= ((uint8_t*)a)[3];
  99. ((uint8_t*)a)[1] ^= ((uint8_t*)a)[2];
  100. ((uint8_t*)a)[2] ^= ((uint8_t*)a)[1];
  101. ((uint8_t*)a)[1] ^= ((uint8_t*)a)[2];
  102. }
  103. static
  104. void changendian(void* a){
  105. changendian32((uint32_t*)(&(((uint32_t*)a)[0])));
  106. changendian32((uint32_t*)(&(((uint32_t*)a)[1])));
  107. changendian32((uint32_t*)(&(((uint32_t*)a)[2])));
  108. changendian32((uint32_t*)(&(((uint32_t*)a)[3])));
  109. }
  110. /******************************************************************************/
  111. void noekeon_enc(void* buffer, const void* key){
  112. uint8_t rc=0x80;
  113. uint8_t keyb[16];
  114. int8_t i;
  115. memcpy(keyb, key, 16);
  116. changendian(buffer);
  117. changendian(keyb);
  118. for(i=0; i<ROUND_NR; ++i){
  119. noekeon_round((uint32_t*)keyb, (uint32_t*)buffer, rc, 0);
  120. #ifdef __AVR__
  121. rc = pgm_read_byte(rc_tab+i);
  122. #else
  123. rc = rc_tab[i];
  124. #endif
  125. }
  126. ((uint8_t*)buffer)[RC_POS] ^= rc;
  127. theta((uint32_t*)keyb, (uint32_t*)buffer);
  128. changendian(buffer);
  129. }
  130. void noekeon_dec(void* buffer, const void* key){
  131. uint8_t rc;
  132. int8_t i;
  133. uint8_t nullv[16];
  134. uint8_t dkey[16];
  135. changendian(buffer);
  136. memset(nullv, 0, 16);
  137. memcpy(dkey, key, 16);
  138. changendian(dkey);
  139. theta((uint32_t*)nullv, (uint32_t*)dkey);
  140. // cli_putstr("\r\nTheta: ");
  141. // cli_hexdump(dkey, 16);
  142. for(i=ROUND_NR-1; i>=0; --i){
  143. #ifdef __AVR__
  144. rc = pgm_read_byte(rc_tab+i);
  145. #else
  146. rc = rc_tab[i];
  147. #endif
  148. noekeon_round((uint32_t*)dkey, (uint32_t*)buffer, 0, rc);
  149. }
  150. theta((uint32_t*)dkey, (uint32_t*)buffer);
  151. ((uint8_t*)buffer)[RC_POS] ^= 0x80;
  152. changendian(buffer);
  153. }
  154. void noekeon_init(const void* key, noekeon_ctx_t* ctx){
  155. uint8_t nullv[16];
  156. memset(nullv, 0, 16);
  157. memcpy(ctx, key, 16);
  158. noekeon_enc(ctx, nullv);
  159. }