better standard compliance
[rofl0r-kripto.git] / lib / block / rc5.c
blob42fe23a06a5b04f4aff1f53baea847715ca6f6cc
1 /*
2 * Copyright (C) 2011, 2013 Gregor Pintar <grpintar@gmail.com>
4 * Permission is granted to deal in this work without any restriction,
5 * including unlimited rights to use, publicly perform, publish,
6 * reproduce, relicence, modify, merge, and/or distribute in any form,
7 * for any purpose, with or without fee, and by any means.
9 * This work is provided "AS IS" and WITHOUT WARRANTY of any kind,
10 * to the utmost extent permitted by applicable law. In no event
11 * shall a licensor, author or contributor be held liable for any
12 * issues arising in any way out of dealing in the work.
15 #include <stdint.h>
16 #include <stdlib.h>
17 #include <limits.h>
19 #include <kripto/cast.h>
20 #include <kripto/loadstore.h>
21 #include <kripto/rotate.h>
22 #include <kripto/memwipe.h>
23 #include <kripto/block.h>
24 #include <kripto/desc/block.h>
25 #include <kripto/object/block.h>
27 #include <kripto/block/rc5.h>
29 struct kripto_block
31 struct kripto_block_object obj;
32 unsigned int rounds;
33 size_t size;
34 uint32_t *k;
37 #define RC5_K_LEN(r) (((r) << 1) + 2)
39 static void rc5_setup
41 kripto_block *s,
42 const uint8_t *key,
43 unsigned int key_len
46 unsigned int i;
47 unsigned int j;
48 unsigned int k;
49 const unsigned int ls = (key_len + 3) >> 2;
50 uint32_t a;
51 uint32_t b;
52 uint32_t x[64];
54 for(i = 0; i < ls; i++) x[i] = 0;
56 for(j = key_len - 1; j != UINT_MAX; j--)
57 x[j >> 2] = (x[j >> 2] << 8) | key[j];
59 *s->k = 0xB7E15163;
60 for(i = 1; i < RC5_K_LEN(s->rounds); i++)
61 s->k[i] = s->k[i-1] + 0x9E3779B9;
63 a = b = i = j = k = 0;
64 while(k < RC5_K_LEN(s->rounds) * 3)
66 a = s->k[i] = ROL32(s->k[i] + a + b, 3);
67 b = x[j] = ROL32(x[j] + a + b, a + b);
68 if(++i == RC5_K_LEN(s->rounds)) i = 0;
69 if(++j == ls) j = 0;
70 k++;
73 /* wipe */
74 kripto_memwipe(x, ls << 2);
75 kripto_memwipe(&a, sizeof(uint32_t));
76 kripto_memwipe(&b, sizeof(uint32_t));
79 static void rc5_encrypt(const kripto_block *s, const void *pt, void *ct)
81 uint32_t a;
82 uint32_t b;
83 unsigned int i = 2;
85 a = LOAD32L(CU8(pt));
86 b = LOAD32L(CU8(pt) + 4);
88 a += s->k[0];
89 b += s->k[1];
91 while(i < s->rounds << 1)
93 a = ROL32(a ^ b, b & 31) + s->k[i++];
94 b = ROL32(b ^ a, a & 31) + s->k[i++];
97 STORE32L(a, U8(ct));
98 STORE32L(b, U8(ct) + 4);
101 static void rc5_decrypt(const kripto_block *s, const void *ct, void *pt)
103 uint32_t a;
104 uint32_t b;
105 unsigned int i = s->rounds << 1;
107 a = LOAD32L(CU8(ct));
108 b = LOAD32L(CU8(ct) + 4);
110 while(--i)
112 b = ROR32(b - s->k[i], a & 31) ^ a;
113 --i;
114 a = ROR32(a - s->k[i], b & 31) ^ b;
117 b -= s->k[1];
118 a -= s->k[0];
120 STORE32L(a, U8(pt));
121 STORE32L(b, U8(pt) + 4);
124 static kripto_block *rc5_create
126 unsigned int r,
127 const void *key,
128 unsigned int key_len
131 kripto_block *s;
133 if(!r) r = 12;
135 s = malloc(sizeof(kripto_block) + (RC5_K_LEN(r) << 2));
136 if(!s) return 0;
138 s->obj.desc = kripto_block_rc5;
139 s->size = sizeof(kripto_block) + (RC5_K_LEN(r) << 2);
140 s->rounds = r;
141 s->k = (uint32_t *)((uint8_t *)s + sizeof(kripto_block));
143 rc5_setup(s, key, key_len);
145 return s;
148 static void rc5_destroy(kripto_block *s)
150 kripto_memwipe(s, s->size);
151 free(s);
154 static kripto_block *rc5_recreate
156 kripto_block *s,
157 unsigned int r,
158 const void *key,
159 unsigned int key_len
162 if(!r) r = 12;
164 if(sizeof(kripto_block) + (RC5_K_LEN(r) << 2) > s->size)
166 rc5_destroy(s);
167 s = rc5_create(r, key, key_len);
169 else
171 s->rounds = r;
172 rc5_setup(s, key, key_len);
175 return s;
178 static const kripto_block_desc rc5 =
180 &rc5_create,
181 &rc5_recreate,
183 &rc5_encrypt,
184 &rc5_decrypt,
185 &rc5_destroy,
186 8, /* block size */
187 255 /* max key */
190 const kripto_block_desc *const kripto_block_rc5 = &rc5;