khazad.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /* khazad.c */
  2. /*
  3. This file is part of the ARM-Crypto-Lib.
  4. Copyright (C) 2006-2011 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. #include <stdint.h>
  17. #include <string.h>
  18. #include <crypto/gf256mul.h>
  19. #include <crypto/memxor.h>
  20. #include <crypto/khazad.h>
  21. /*
  22. | | | | | | | |
  23. V V V V V V V V
  24. +-------+ +-------+
  25. | P | | Q |
  26. +-------+ +-------+
  27. | | \ \ / / | |
  28. | | \ \ / / | |
  29. | | \ \ / / | |
  30. | | \ X / | |
  31. | | X X | |
  32. | | / X \ | |
  33. | | / / \ \ | |
  34. | | / / \ \ | |
  35. | | / / \ \ | |
  36. | | | | | | | |
  37. V V V V V V V V
  38. +-------+ +-------+
  39. | Q | | P |
  40. +-------+ +-------+
  41. | | \ \ / / | |
  42. | | \ \ / / | |
  43. | | \ \ / / | |
  44. | | \ X / | |
  45. | | X X | |
  46. | | / X \ | |
  47. | | / / \ \ | |
  48. | | / / \ \ | |
  49. | | / / \ \ | |
  50. | | | | | | | |
  51. V V V V V V V V
  52. +-------+ +-------+
  53. | P | | Q |
  54. +-------+ +-------+
  55. | | | | | | | |
  56. V V V V V V V V
  57. P:
  58. 3x Fx Ex 0x 5x 4x Bx Cx Dx Ax 9x 6x 7x 8x 2x 1x
  59. Q:
  60. 9x Ex 5x 6x Ax 2x 3x Cx Fx 0x 4x Dx 7x Bx 1x 8x
  61. */
  62. static const uint8_t pq_lut[16] = {
  63. 0x39, 0xFE, 0xE5, 0x06, 0x5A, 0x42, 0xB3, 0xCC,
  64. 0xDF, 0xA0, 0x94, 0x6D, 0x77, 0x8B, 0x21, 0x18
  65. };
  66. uint8_t khazad_sbox(uint8_t a){
  67. uint8_t b,c,d,e;
  68. b = pq_lut[a>>4] & 0xf0;
  69. c = pq_lut[a&0xf] & 0x0f;
  70. d = (b>>2)&0x0c;
  71. e = (c<<2)&0x30;
  72. b = (b&0xc0)|e;
  73. c = (c&0x03)|d;
  74. b = pq_lut[b>>4] << 4;
  75. c = pq_lut[c&0xf] >> 4;
  76. d = (b>>2)&0x0c;
  77. e = (c<<2)&0x30;
  78. b = (b&0xc0)|e;
  79. c = (c&0x03)|d;
  80. b = pq_lut[b>>4] & 0xf0;
  81. c = pq_lut[c&0xf] & 0x0f;
  82. return b|c;
  83. }
  84. static void gamma_x(uint8_t* a){
  85. uint8_t i;
  86. for(i=0; i<8; ++i){
  87. *a = khazad_sbox(*a);
  88. a++;
  89. }
  90. }
  91. /******************************************************************************/
  92. /* p8 (x) = x^8 + x^4 + x^3 + x^2 + 1 */
  93. #define POLYNOM 0x1D
  94. /*
  95. * 01x 03x 04x 05x 06x 08x 0Bx 07x
  96. * 03x 01x 05x 04x 08x 06x 07x 0Bx
  97. * 04x 05x 01x 03x 0Bx 07x 06x 08x
  98. * 05x 04x 03x 01x 07x 0Bx 08x 06x
  99. * 06x 08x 0Bx 07x 01x 03x 04x 05x
  100. * 08x 06x 07x 0Bx 03x 01x 05x 04x
  101. * 0Bx 07x 06x 08x 04x 05x 01x 03x
  102. * 07x 0Bx 08x 06x 05x 04x 03x 01x
  103. */
  104. static const uint8_t h[8][4] = {
  105. { 0x13, 0x45, 0x68, 0xB7 },
  106. { 0x31, 0x54, 0x86, 0x7B },
  107. { 0x45, 0x13, 0xB7, 0x68 },
  108. { 0x54, 0x31, 0x7B, 0x86 },
  109. { 0x68, 0xB7, 0x13, 0x45 },
  110. { 0x86, 0x7B, 0x31, 0x54 },
  111. { 0xB7, 0x68, 0x45, 0x13 },
  112. { 0x7B, 0x86, 0x54, 0x31 }
  113. };
  114. static void theta(uint8_t* a){
  115. uint8_t i,j,x,accu;
  116. uint8_t c[8];
  117. uint8_t *hp;
  118. hp = (uint8_t*)h;
  119. for(i=0; i<8; ++i){
  120. accu = 0;
  121. for(j=0; j<4; ++j){
  122. x = *hp++;
  123. accu ^= gf256mul(*a++, x>>4, POLYNOM);
  124. accu ^= gf256mul(*a++, x&0xf, POLYNOM);
  125. }
  126. a -= 8;
  127. c[i] = accu;
  128. }
  129. memcpy(a, c, 8);
  130. }
  131. /******************************************************************************/
  132. static void khazad_round(uint8_t* a, const uint8_t* k){
  133. gamma_x(a);
  134. theta(a);
  135. memxor(a, k, 8);
  136. }
  137. /******************************************************************************/
  138. void khazad_init(const void* key, khazad_ctx_t* ctx){
  139. uint8_t c[8];
  140. uint8_t i,r=0;
  141. for(i=0; i<8; ++i){
  142. c[i] = khazad_sbox(r*8+i);
  143. }
  144. memcpy(ctx->k[r], (uint8_t*)key+8, 8);
  145. khazad_round(ctx->k[r], c);
  146. memxor(ctx->k[r], (uint8_t*)key, 8);
  147. r=1;
  148. for(i=0; i<8; ++i){
  149. c[i] = khazad_sbox(r*8+i);
  150. }
  151. memcpy(ctx->k[r], ctx->k[r-1], 8);
  152. khazad_round(ctx->k[r], c);
  153. memxor(ctx->k[r], (uint8_t*)key+8, 8);
  154. for(r=2; r<9; ++r){
  155. for(i=0; i<8; ++i){
  156. c[i] = khazad_sbox(r*8+i);
  157. }
  158. memcpy(ctx->k[r], ctx->k[r-1], 8);
  159. khazad_round(ctx->k[r], c);
  160. memxor(ctx->k[r], ctx->k[r-2], 8);
  161. }
  162. }
  163. /******************************************************************************/
  164. void khazad_enc(void* buffer, const khazad_ctx_t* ctx){
  165. uint8_t r;
  166. memxor(buffer, ctx->k[0], 8);
  167. for(r=1; r<8; ++r){
  168. khazad_round(buffer, ctx->k[r]);
  169. }
  170. gamma_x(buffer);
  171. memxor(buffer, ctx->k[8], 8);
  172. }
  173. /******************************************************************************/
  174. void khazad_dec(void* buffer, const khazad_ctx_t* ctx){
  175. uint8_t r=7;
  176. memxor(buffer, ctx->k[8], 8);
  177. gamma_x(buffer);
  178. do{
  179. memxor(buffer, ctx->k[r--], 8);
  180. theta(buffer);
  181. gamma_x(buffer);
  182. }while(r);
  183. memxor(buffer, ctx->k[0], 8);
  184. }