2 * Written in 2011 by Gregor Pintar <grpintar@gmail.com>
4 * To the extent possible under law, the author(s) have dedicated
5 * all copyright and related and neighboring rights to this software
6 * to the public domain worldwide.
8 * This software is distributed without any warranty.
10 * You should have received a copy of the CC0 Public Domain Dedication.
11 * If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
18 #include <kripto/cast.h>
19 #include <kripto/loadstore.h>
20 #include <kripto/rotate.h>
21 #include <kripto/memwipe.h>
22 #include <kripto/block.h>
23 #include <kripto/desc/block.h>
24 #include <kripto/object/block.h>
26 #include <kripto/block/rc6.h>
30 struct kripto_block_object obj
;
36 #define RC6_K_LEN(r) (((r) + 2) << 1)
48 const unsigned int ls
= (key_len
+ 3) >> 2;
53 for(i
= 0; i
< ls
; i
++) x
[i
] = 0;
55 for(j
= key_len
- 1; j
!= UINT_MAX
; j
--)
56 x
[j
>> 2] = (x
[j
>> 2] << 8) | key
[j
];
59 for(i
= 1; i
< RC6_K_LEN(s
->rounds
); i
++)
60 s
->k
[i
] = s
->k
[i
-1] + 0x9E3779B9;
62 a
= b
= i
= j
= k
= 0;
63 while(k
< RC6_K_LEN(s
->rounds
) * 3)
65 a
= s
->k
[i
] = ROL32(s
->k
[i
] + a
+ b
, 3);
66 b
= x
[j
] = ROL32(x
[j
] + a
+ b
, a
+ b
);
67 if(++i
== RC6_K_LEN(s
->rounds
)) i
= 0;
73 kripto_memwipe(x
, ls
<< 2);
74 kripto_memwipe(&a
, sizeof(uint32_t));
75 kripto_memwipe(&b
, sizeof(uint32_t));
78 static void rc6_encrypt(const kripto_block
*s
, const void *pt
, void *ct
)
90 b
= LOAD32L(CU8(pt
) + 4);
91 c
= LOAD32L(CU8(pt
) + 8);
92 d
= LOAD32L(CU8(pt
) + 12);
97 while(i
<= (s
->rounds
<< 1))
99 m0
= ROL32(b
* ((b
<< 1) | 1), 5);
100 m1
= ROL32(d
* ((d
<< 1) | 1), 5);
102 t
= ROL32(a
^ m0
, m1
) + s
->k
[i
++];
104 b
= ROL32(c
^ m1
, m0
) + s
->k
[i
++];
113 STORE32L(b
, U8(ct
) + 4);
114 STORE32L(c
, U8(ct
) + 8);
115 STORE32L(d
, U8(ct
) + 12);
118 static void rc6_decrypt(const kripto_block
*s
, const void *ct
, void *pt
)
127 unsigned int i
= s
->rounds
<< 1;
129 a
= LOAD32L(CU8(ct
));
130 b
= LOAD32L(CU8(ct
) + 4);
131 c
= LOAD32L(CU8(ct
) + 8);
132 d
= LOAD32L(CU8(ct
) + 12);
139 m0
= ROL32(a
* ((a
<< 1) | 1), 5);
140 m1
= ROL32(c
* ((c
<< 1) | 1), 5);
144 c
= ROR32(b
- s
->k
[i
+ 1], m0
) ^ m1
;
146 a
= ROR32(t
- s
->k
[i
], m1
) ^ m0
;
155 STORE32L(b
, U8(pt
) + 4);
156 STORE32L(c
, U8(pt
) + 8);
157 STORE32L(d
, U8(pt
) + 12);
160 static kripto_block
*rc6_create
171 s
= malloc(sizeof(kripto_block
) + (RC6_K_LEN(r
) << 2));
174 s
->obj
.desc
= kripto_block_rc6
;
175 s
->size
= sizeof(kripto_block
) + (RC6_K_LEN(r
) << 2);
177 s
->k
= (uint32_t *)((uint8_t *)s
+ sizeof(kripto_block
));
179 rc6_setup(s
, key
, key_len
);
184 static void rc6_destroy(kripto_block
*s
)
186 kripto_memwipe(s
, s
->size
);
190 static kripto_block
*rc6_recreate
200 if(sizeof(kripto_block
) + (RC6_K_LEN(r
) << 2) > s
->size
)
203 s
= rc6_create(r
, key
, key_len
);
208 rc6_setup(s
, key
, key_len
);
214 static const kripto_block_desc rc6
=
227 const kripto_block_desc
*const kripto_block_rc6
= &rc6
;