cast5.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. /* cast5.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. * \file cast5.c
  18. * \author Daniel Otte
  19. * \email daniel.otte@rub.de
  20. * \date 2006-07-26
  21. * \par License:
  22. * GPLv3 or later
  23. * \brief Implementation of the CAST5 (aka CAST-128) cipher algorithm as described in RFC 2144
  24. *
  25. */
  26. #include <stdint.h>
  27. #include <string.h>
  28. #include <crypto/cast5.h>
  29. #include"config.h"
  30. #undef DEBUG
  31. #ifdef DEBUG
  32. #include "cli.h"
  33. #endif
  34. #include <crypto/cast5-sbox.h>
  35. #define S5(x) (s5[(x)])
  36. #define S6(x) (s6[(x)])
  37. #define S7(x) (s7[(x)])
  38. #define S8(x) (s8[(x)])
  39. static
  40. void cast5_init_A(uint8_t *dest, uint8_t *src, bool bmode){
  41. uint8_t mask = bmode?0x8:0;
  42. *((uint32_t*)(&dest[0x0])) = *((uint32_t*)(&src[0x0^mask]))
  43. ^ S5(src[0xD^mask]) ^ S6(src[0xF^mask])
  44. ^ S7(src[0xC^mask]) ^ S8(src[0xE^mask])
  45. ^ S7(src[0x8^mask]);
  46. *((uint32_t*)(&dest[0x4])) = *((uint32_t*)(&src[0x8^mask]))
  47. ^ S5(dest[0x0]) ^ S6(dest[0x2])
  48. ^ S7(dest[0x1]) ^ S8(dest[0x3])
  49. ^ S8(src[0xA^mask]);
  50. *((uint32_t*)(&dest[0x8])) = *((uint32_t*)(&src[0xC^mask]))
  51. ^ S5(dest[0x7]) ^ S6(dest[0x6])
  52. ^ S7(dest[0x5]) ^ S8(dest[0x4])
  53. ^ S5(src[0x9^mask]);
  54. *((uint32_t*)(&dest[0xC])) = *((uint32_t*)(&src[0x4^mask]))
  55. ^ S5(dest[0xA])
  56. ^ S6(dest[0x9])
  57. ^ S7(dest[0xB])
  58. ^ S8(dest[0x8])
  59. ^ S6(src[0xB^mask]);
  60. }
  61. static
  62. void cast5_init_M(uint8_t *dest, uint8_t *src, bool nmode, bool xmode){
  63. uint8_t nmt[] = {0xB, 0xA, 0x9, 0x8,
  64. 0xF, 0xE, 0xD, 0xC,
  65. 0x3, 0x2, 0x1, 0x0,
  66. 0x7, 0x6, 0x5, 0x4}; /* nmode table */
  67. uint8_t xmt[4][4] = {{0x2, 0x6, 0x9, 0xC},
  68. {0x8, 0xD, 0x3, 0x7},
  69. {0x3, 0x7, 0x8, 0xD},
  70. {0x9, 0xC, 0x2, 0x6}};
  71. #define NMT(x) (src[nmode?nmt[(x)]:(x)])
  72. #define XMT(x) (src[xmt[(xmode<<1) + nmode][(x)]])
  73. *((uint32_t*)(&dest[0x0])) = S5(NMT(0x8)) ^ S6(NMT(0x9)) ^ S7(NMT(0x7)) ^ S8(NMT(0x6)) ^ S5(XMT(0));
  74. *((uint32_t*)(&dest[0x4])) = S5(NMT(0xA)) ^ S6(NMT(0xB)) ^ S7(NMT(0x5)) ^ S8(NMT(0x4)) ^ S6(XMT(1));
  75. *((uint32_t*)(&dest[0x8])) = S5(NMT(0xC)) ^ S6(NMT(0xD)) ^ S7(NMT(0x3)) ^ S8(NMT(0x2)) ^ S7(XMT(2));
  76. *((uint32_t*)(&dest[0xC])) = S5(NMT(0xE)) ^ S6(NMT(0xF)) ^ S7(NMT(0x1)) ^ S8(NMT(0x0)) ^ S8(XMT(3));
  77. }
  78. #define S5B(x) *(3+(uint8_t*)(&s5[(x)]))
  79. #define S6B(x) *(3+(uint8_t*)(&s6[(x)]))
  80. #define S7B(x) *(3+(uint8_t*)(&s7[(x)]))
  81. #define S8B(x) *(3+(uint8_t*)(&s8[(x)]))
  82. static
  83. void cast5_init_rM(uint8_t *klo, uint8_t *khi, uint8_t offset, uint8_t *src, bool nmode, bool xmode){
  84. uint8_t nmt[] = {0xB, 0xA, 0x9, 0x8, 0xF, 0xE, 0xD, 0xC, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4}; /* nmode table */
  85. uint8_t xmt[4][4] = {{0x2, 0x6, 0x9, 0xC}, {0x8, 0xD, 0x3, 0x7}, {0x3, 0x7, 0x8, 0xD}, {0x9, 0xC, 0x2, 0x6}};
  86. uint8_t t, h=0;
  87. t = S5B(NMT(0x8)) ^ S6B(NMT(0x9)) ^ S7B(NMT(0x7)) ^ S8B(NMT(0x6)) ^ S5B(XMT(0));
  88. klo[offset*2] |= (t & 0x0f);
  89. h |= (t&0x10); h>>=1;
  90. t = S5B(NMT(0xA)) ^ S6B(NMT(0xB)) ^ S7B(NMT(0x5)) ^ S8B(NMT(0x4)) ^ S6B(XMT(1));
  91. klo[offset*2] |= (t<<4) & 0xf0;
  92. h |= t&0x10; h>>=1;
  93. t = S5B(NMT(0xC)) ^ S6B(NMT(0xD)) ^ S7B(NMT(0x3)) ^ S8B(NMT(0x2)) ^ S7B(XMT(2));
  94. klo[offset*2+1] |= t&0xf;
  95. h |= t&0x10; h>>=1;
  96. t = S5B(NMT(0xE)) ^ S6B(NMT(0xF)) ^ S7B(NMT(0x1)) ^ S8B(NMT(0x0)) ^ S8B(XMT(3));
  97. klo[offset*2+1] |= t<<4;
  98. h |= t&0x10; h >>=1;
  99. #ifdef DEBUG
  100. cli_putstr("\r\n\t h="); cli_hexdump(&h,1);
  101. #endif
  102. khi[offset>>1] |= h<<((offset&0x1)?4:0);
  103. }
  104. #define S_5X(s) (s5[BPX[(s)]])
  105. #define S_6X(s) (s6[BPX[(s)]])
  106. #define S_7X(s) (s7[BPX[(s)]])
  107. #define S_8X(s) (s8[BPX[(s)]])
  108. #define S_5Z(s) (s5[BPZ[(s)]])
  109. #define S_6Z(s) (s6[BPZ[(s)]])
  110. #define S_7Z(s) (s7[BPZ[(s)]])
  111. #define S_8Z(s) (s8[BPZ[(s)]])
  112. void cast5_init(const void* key, uint16_t keylength_b, cast5_ctx_t* s){
  113. /* we migth return if the key is valid and if setup was successful */
  114. uint32_t x[4], z[4];
  115. #define BPX ((uint8_t*)&(x[0]))
  116. #define BPZ ((uint8_t*)&(z[0]))
  117. s->shortkey = (keylength_b<=80);
  118. /* littel endian only! */
  119. memset(&(x[0]), 0 ,16); /* set x to zero */
  120. if(keylength_b > 128)
  121. keylength_b=128;
  122. memcpy(&(x[0]), key, (keylength_b+7)/8);
  123. /* todo: merge a and b and compress the whole stuff */
  124. /***** A *****/
  125. cast5_init_A((uint8_t*)(&z[0]), (uint8_t*)(&x[0]), false);
  126. /***** M *****/
  127. cast5_init_M((uint8_t*)(&(s->mask[0])), (uint8_t*)(&z[0]), false, false);
  128. /***** B *****/
  129. cast5_init_A((uint8_t*)(&x[0]), (uint8_t*)(&z[0]), true);
  130. /***** N *****/
  131. cast5_init_M((uint8_t*)(&(s->mask[4])), (uint8_t*)(&x[0]), true, false);
  132. /***** A *****/
  133. cast5_init_A((uint8_t*)(&z[0]), (uint8_t*)(&x[0]), false);
  134. /***** N' *****/
  135. cast5_init_M((uint8_t*)(&(s->mask[8])), (uint8_t*)(&z[0]), true, true);
  136. /***** B *****/
  137. cast5_init_A((uint8_t*)(&x[0]), (uint8_t*)(&z[0]), true);
  138. /***** M' *****/
  139. cast5_init_M((uint8_t*)(&(s->mask[12])), (uint8_t*)(&x[0]), false, true);
  140. /* that were the masking keys, now the rotation keys */
  141. /* set the keys to zero */
  142. memset(&(s->rotl[0]),0,8);
  143. s->roth[0]=s->roth[1]=0;
  144. /***** A *****/
  145. cast5_init_A((uint8_t*)(&z[0]), (uint8_t*)(&x[0]), false);
  146. /***** M *****/
  147. cast5_init_rM(&(s->rotl[0]), &(s->roth[0]), 0, (uint8_t*)(&z[0]), false, false);
  148. /***** B *****/
  149. cast5_init_A((uint8_t*)(&x[0]), (uint8_t*)(&z[0]), true);
  150. /***** N *****/
  151. cast5_init_rM(&(s->rotl[0]), &(s->roth[0]), 1, (uint8_t*)(&x[0]), true, false);
  152. /***** A *****/
  153. cast5_init_A((uint8_t*)(&z[0]), (uint8_t*)(&x[0]), false);
  154. /***** N' *****/
  155. cast5_init_rM(&(s->rotl[0]), &(s->roth[0]), 2, (uint8_t*)(&z[0]), true, true);
  156. /***** B *****/
  157. cast5_init_A((uint8_t*)(&x[0]), (uint8_t*)(&z[0]), true);
  158. /***** M' *****/
  159. cast5_init_rM(&(s->rotl[0]), &(s->roth[0]), 3, (uint8_t*)(&x[0]), false, true);
  160. /* done ;-) */
  161. }
  162. /********************************************************************************************************/
  163. #define ROTL32(a,n) ((a)<<(n) | (a)>>(32-(n)))
  164. #define CHANGE_ENDIAN32(x) ((x)<<24 | (x)>>24 | ((x)&0xff00)<<8 | ((x)&0xff0000)>>8 )
  165. typedef uint32_t cast5_f_t(uint32_t,uint32_t,uint8_t);
  166. #define IA 3
  167. #define IB 2
  168. #define IC 1
  169. #define ID 0
  170. static
  171. uint32_t cast5_f1(uint32_t d, uint32_t m, uint8_t r){
  172. uint32_t t;
  173. t = ROTL32((d + m),r);
  174. #ifdef DEBUG
  175. uint32_t ia,ib,ic,id;
  176. cli_putstr("\r\n f1("); cli_hexdump(&d, 4); cli_putc(',');
  177. cli_hexdump(&m , 4); cli_putc(','); cli_hexdump(&r, 1);cli_putstr("): I=");
  178. cli_hexdump(&t, 4);
  179. ia = s1[((uint8_t*)&t)[IA]];
  180. ib = s2[((uint8_t*)&t)[IB]];
  181. ic = s3[((uint8_t*)&t)[IC]];
  182. id = s4[((uint8_t*)&t)[ID]];
  183. cli_putstr("\r\n\tIA="); cli_hexdump(&ia, 4);
  184. cli_putstr("\r\n\tIB="); cli_hexdump(&ib, 4);
  185. cli_putstr("\r\n\tIC="); cli_hexdump(&ic, 4);
  186. cli_putstr("\r\n\tID="); cli_hexdump(&id, 4);
  187. return (((ia ^ ib) - ic) + id);
  188. #else
  189. return ((( s1[((uint8_t*)&t)[IA]]
  190. ^ s2[((uint8_t*)&t)[IB]] )
  191. - s3[((uint8_t*)&t)[IC]] )
  192. + s4[((uint8_t*)&t)[ID]] );
  193. #endif
  194. }
  195. static
  196. uint32_t cast5_f2(uint32_t d, uint32_t m, uint8_t r){
  197. uint32_t t;
  198. t = ROTL32((d ^ m),r);
  199. #ifdef DEBUG
  200. uint32_t ia,ib,ic,id;
  201. cli_putstr("\r\n f2("); cli_hexdump(&d, 4); cli_putc(',');
  202. cli_hexdump(&m , 4); cli_putc(','); cli_hexdump(&r, 1);cli_putstr("): I=");
  203. cli_hexdump(&t, 4);
  204. ia = s1[((uint8_t*)&t)[IA]];
  205. ib = s2[((uint8_t*)&t)[IB]];
  206. ic = s3[((uint8_t*)&t)[IC]];
  207. id = s4[((uint8_t*)&t)[ID]];
  208. cli_putstr("\r\n\tIA="); cli_hexdump(&ia, 4);
  209. cli_putstr("\r\n\tIB="); cli_hexdump(&ib, 4);
  210. cli_putstr("\r\n\tIC="); cli_hexdump(&ic, 4);
  211. cli_putstr("\r\n\tID="); cli_hexdump(&id, 4);
  212. return (((ia - ib) + ic) ^ id);
  213. #else
  214. return ((( s1[((uint8_t*)&t)[IA]]
  215. - s2[((uint8_t*)&t)[IB]] )
  216. + s3[((uint8_t*)&t)[IC]] )
  217. ^ s4[((uint8_t*)&t)[ID]] );
  218. #endif
  219. }
  220. static
  221. uint32_t cast5_f3(uint32_t d, uint32_t m, uint8_t r){
  222. uint32_t t;
  223. t = ROTL32((m - d),r);
  224. #ifdef DEBUG
  225. uint32_t ia,ib,ic,id;
  226. cli_putstr("\r\n f3("); cli_hexdump(&d, 4); cli_putc(',');
  227. cli_hexdump(&m , 4); cli_putc(','); cli_hexdump(&r, 1);cli_putstr("): I=");
  228. cli_hexdump(&t, 4);
  229. ia = s1[((uint8_t*)&t)[IA]];
  230. ib = s2[((uint8_t*)&t)[IB]];
  231. ic = s3[((uint8_t*)&t)[IC]];
  232. id = s4[((uint8_t*)&t)[ID]];
  233. cli_putstr("\r\n\tIA="); cli_hexdump(&ia, 4);
  234. cli_putstr("\r\n\tIB="); cli_hexdump(&ib, 4);
  235. cli_putstr("\r\n\tIC="); cli_hexdump(&ic, 4);
  236. cli_putstr("\r\n\tID="); cli_hexdump(&id, 4);
  237. return (((ia + ib) ^ ic) - id);
  238. #else
  239. return (( s1[((uint8_t*)&t)[IA]]
  240. + s2[((uint8_t*)&t)[IB]])
  241. ^ s3[((uint8_t*)&t)[IC]])
  242. - s4[((uint8_t*)&t)[ID]];
  243. #endif
  244. }
  245. /******************************************************************************/
  246. void cast5_enc(void* block, const cast5_ctx_t *s){
  247. uint32_t l,r, x, y;
  248. uint8_t i;
  249. cast5_f_t* f[]={cast5_f1,cast5_f2,cast5_f3};
  250. l=((uint32_t*)block)[0];
  251. r=((uint32_t*)block)[1];
  252. // cli_putstr("\r\n round[-1] = ");
  253. // cli_hexdump(&r, 4);
  254. for (i=0;i<(s->shortkey?12:16);++i){
  255. x = r;
  256. y = (f[i%3])(CHANGE_ENDIAN32(r), CHANGE_ENDIAN32(s->mask[i]),
  257. (((s->roth[i>>3]) & (1<<(i&0x7)))?0x10:0x00)
  258. + ( ((s->rotl[i>>1])>>((i&1)?4:0)) & 0x0f) );
  259. r = l ^ CHANGE_ENDIAN32(y);
  260. // cli_putstr("\r\n round["); DEBUG_B(i); cli_putstr("] = ");
  261. // cli_hexdump(&r, 4);
  262. l = x;
  263. }
  264. ((uint32_t*)block)[0]=r;
  265. ((uint32_t*)block)[1]=l;
  266. }
  267. /******************************************************************************/
  268. void cast5_dec(void* block, const cast5_ctx_t *s){
  269. uint32_t l,r, x, y;
  270. int8_t i, rounds;
  271. cast5_f_t* f[]={cast5_f1,cast5_f2,cast5_f3};
  272. l=((uint32_t*)block)[0];
  273. r=((uint32_t*)block)[1];
  274. rounds = (s->shortkey?12:16);
  275. for (i=rounds-1; i>=0 ;--i){
  276. x = r;
  277. y = (f[i%3])(CHANGE_ENDIAN32(r), CHANGE_ENDIAN32(s->mask[i]),
  278. (((s->roth[i>>3]) & (1<<(i&0x7)))?0x10:0x00)
  279. + ( ((s->rotl[i>>1])>>((i&1)?4:0)) & 0x0f) );
  280. r = l ^ CHANGE_ENDIAN32(y);
  281. l = x;
  282. }
  283. ((uint32_t*)block)[0]=r;
  284. ((uint32_t*)block)[1]=l;
  285. }
  286. /******************************************************************************/